diff --git a/.idea/compiler.xml b/.idea/compiler.xml index fb7f4a8a465d42b4a0390d464b83b99e8465bba7..61a9130cd9669c3843e6445dfe1fee2d493869bc 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="CompilerConfiguration"> - <bytecodeTargetLevel target="11" /> + <bytecodeTargetLevel target="1.8" /> </component> </project> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index ef61796f57624d99df9ef9b2479763aed4ad62eb..d5d35ec44f10991b508f6454a85204a276726364 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="1.8" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/build/classes" /> </component> <component name="ProjectType"> diff --git a/CHANGES.md b/CHANGES.md index 71ad471453558637894bb01dd19278b620b39bd4..292e34de5a789dd3ddeba696170a0b719610af50 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,28 @@ Please also refer to the Changelog of Element Android: https://github.com/vector-im/element-android/blob/main/CHANGES.md +Changes in Matrix-SDK 1.4.14 (2022-05-10) +=================================================== + +Imported from Element 1.4.14. (https://github.com/vector-im/element-android/releases/tag/v1.4.14) + +Bugfixes 🛠+---------- +- Fixes crash when accepting or receiving VOIP calls ([#5421](https://github.com/vector-im/element-android/issues/5421)) +- Improve/fix crashes on messages decryption ([#5592](https://github.com/vector-im/element-android/issues/5592)) +- Don't pause timer when call is held. ([#5885](https://github.com/vector-im/element-android/issues/5885)) + +SDK API changes âš ï¸ +------------------ +- Added registrationCustom into RegistrationWizard to send custom auth params for sign up +- Moved terms converter into api package to make it accessible in sdk ([#5575](https://github.com/vector-im/element-android/issues/5575)) +- Move package `org.matrix.android.sdk.api.pushrules` to `org.matrix.android.sdk.api.session.pushrules` ([#5812](https://github.com/vector-im/element-android/issues/5812)) +- Some `Session` apis are now available by requesting the service first. For instance `Session.updateAvatar(...)` is now `Session.profileService().updateAvatar(...)` +- The shortcut `Room.search()` has been removed, you have to use `Session.searchService().search()` ([#5816](https://github.com/vector-im/element-android/issues/5816)) +- Add return type to RoomApi.sendStateEvent() to retrieve the created event id ([#5855](https://github.com/vector-im/element-android/issues/5855)) +- `Room` apis are now available by requesting the service first. For instance `Room.updateAvatar(...)` is now `Room.stateService().updateAvatar(...)` ([#5858](https://github.com/vector-im/element-android/issues/5858)) +- Remove unecessary field `eventId` from `EventAnnotationsSummary` and `ReferencesAggregatedSummary` ([#5890](https://github.com/vector-im/element-android/issues/5890)) +- Replace usage of `System.currentTimeMillis()` by a `Clock` interface ([#5907](https://github.com/vector-im/element-android/issues/5907)) + Changes in Matrix-SDK 1.4.13 (2022-04-26) =================================================== diff --git a/gradle.properties b/gradle.properties index 99aa02f1355b7f2cfbb32cf3b73d6b5377896b08..6402e3ad3a9b07b41f5e6aa166f272d93357f297 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,7 +26,7 @@ vector.httpLogLevel=NONE # Ref: https://github.com/vanniktech/gradle-maven-publish-plugin GROUP=org.matrix.android POM_ARTIFACT_ID=matrix-android-sdk2 -VERSION_NAME=1.4.13 +VERSION_NAME=1.4.14 POM_PACKAGING=aar diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 18f4325027d6b4c8ffe8b7339155a2ed2115f985..8362d35960f8a43d103a6599481dfe6d90c2fba3 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -16,6 +16,27 @@ buildscript { } } +dokkaHtml { + dokkaSourceSets { + configureEach { + // Emit warnings about not documented members. + reportUndocumented.set(true) + // Suppress legacy Riot's packages. + perPackageOption { + matchingRegex.set("org.matrix.android.sdk.internal.legacy.riot") + suppress.set(true) + } + perPackageOption { + matchingRegex.set("org.matrix.androidsdk.crypto.data") + suppress.set(true) + } + // List of files with module and package documentation + // https://kotlinlang.org/docs/reference/kotlin-doc.html#module-and-package-documentation + includes.from("./docs/modules.md", "./docs/packages.md") + } + } +} + android { testOptions.unitTests.includeAndroidResources = true @@ -174,7 +195,7 @@ dependencies { implementation libs.apache.commonsImaging // Phone number https://github.com/google/libphonenumber - implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.46' + implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.47' testImplementation libs.tests.junit testImplementation 'org.robolectric:robolectric:4.7.3' diff --git a/matrix-sdk-android/docs/modules.md b/matrix-sdk-android/docs/modules.md new file mode 100644 index 0000000000000000000000000000000000000000..edf5af64d024d6a214e3657bc73701ec4182b214 --- /dev/null +++ b/matrix-sdk-android/docs/modules.md @@ -0,0 +1,18 @@ +# Module matrix-sdk-android + +## Welcome to the matrix-sdk-android documentation! + +This pages list the complete API that this SDK is exposing to a client application. + +*We are still building the documentation, so everything is not documented yet.* + +A few entry points: + +- **Matrix**: The app will have to create and manage a Matrix object. +- From this **Matrix** object, you will be able to get various services, including the **AuthenticationService**. +- With this **AuthenticationService** you will be able to get an existing **Session**, or create one using a **LoginWizard** or a **RegistrationWizard**, which will finally give you a **Session**. +- From the **Session**, you will be able to retrieve many Services, including the **RoomService**. +- From the **RoomService**, you will be able to list the rooms, create a **Room**, and get a specific **Room**. +- And from a **Room**, you will be able to do many things, including get a **Timeline**, send messages, etc. + +Please read the whole documentation to learn more! diff --git a/matrix-sdk-android/docs/packages.md b/matrix-sdk-android/docs/packages.md new file mode 100644 index 0000000000000000000000000000000000000000..ae7bee1b4e0c8fb954fc39629e87dc79aafa26fd --- /dev/null +++ b/matrix-sdk-android/docs/packages.md @@ -0,0 +1,3 @@ +# Package org.matrix.android.sdk.api + +This is the root package of the API exposed by this SDK. diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt index 933074cdce2dc14f6c7d22b85ceaa2645db70d95..6d740c5a3421c5668b3fb13c5583f69ebe980944 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt @@ -46,7 +46,7 @@ class ChangePasswordTest : InstrumentedTest { // Change password commonTestHelper.runBlockingTest { - session.changePassword(TestConstants.PASSWORD, NEW_PASSWORD) + session.accountService().changePassword(TestConstants.PASSWORD, NEW_PASSWORD) } // Try to login with the previous password, it will fail diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt index f8d108fb739c232140744e0ac3b358bbfabbb834..52dbfc7155b53f10b188dd845a02ee486efc2b26 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt @@ -47,7 +47,7 @@ class DeactivateAccountTest : InstrumentedTest { // Deactivate the account commonTestHelper.runBlockingTest { - session.deactivateAccount( + session.accountService().deactivateAccount( eraseAllData = false, userInteractiveAuthInterceptor = object : UserInteractiveAuthInterceptor { override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index ac4ccf56d109768ba72e978dff23c5710d005522..4b9e605cd0a54e068b1c6cdb5bad94e6f228bb18 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -57,7 +57,8 @@ import java.util.concurrent.TimeUnit class CommonTestHelper(context: Context) { internal val matrix: TestMatrix - val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) + private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) + private var accountNumber = 0 fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor @@ -145,7 +146,7 @@ class CommonTestHelper(context: Context) { * @param nbOfMessages the number of time the message will be sent */ fun sendTextMessage(room: Room, message: String, nbOfMessages: Int, timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> { - val timeline = room.createTimeline(null, TimelineSettings(10)) + val timeline = room.timelineService().createTimeline(null, TimelineSettings(10)) timeline.start() val sentEvents = sendTextMessagesBatched(timeline, room, message, nbOfMessages, timeout) timeline.dispose() @@ -165,11 +166,12 @@ class CommonTestHelper(context: Context) { .forEach { batchedMessages -> batchedMessages.forEach { formattedMessage -> if (rootThreadEventId != null) { - room.replyInThread( + room.relationService().replyInThread( rootThreadEventId = rootThreadEventId, - replyInThreadText = formattedMessage) + replyInThreadText = formattedMessage + ) } else { - room.sendTextMessage(formattedMessage) + room.sendService().sendTextMessage(formattedMessage) } } waitWithLatch(timeout) { latch -> @@ -214,7 +216,7 @@ class CommonTestHelper(context: Context) { numberOfMessages: Int, rootThreadEventId: String, timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> { - val timeline = room.createTimeline(null, TimelineSettings(10)) + val timeline = room.timelineService().createTimeline(null, TimelineSettings(10)) timeline.start() val sentEvents = sendTextMessagesBatched(timeline, room, message, numberOfMessages, timeout, rootThreadEventId) timeline.dispose() @@ -237,7 +239,7 @@ class CommonTestHelper(context: Context) { password: String, testParams: SessionTestParams): Session { val session = createAccountAndSync( - userNamePrefix + "_" + System.currentTimeMillis() + UUID.randomUUID(), + userNamePrefix + "_" + accountNumber++ + "_" + UUID.randomUUID(), password, testParams ) @@ -431,7 +433,7 @@ class CommonTestHelper(context: Context) { fun signOutAndClose(session: Session) { runBlockingTest(timeout = 60_000) { - session.signOut(true) + session.signOutService().signOut(true) } // no need signout will close // session.close() diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt index e3ab1a4921a5d943a9cacf4a26b4263bc0e39692..058b1f79338237569877e21ee8c255e0a0987e90 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt @@ -40,6 +40,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxStat import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -64,12 +65,12 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams) val roomId = testHelper.runBlockingTest { - aliceSession.createRoom(CreateRoomParams().apply { name = "MyRoom" }) + aliceSession.roomService().createRoom(CreateRoomParams().apply { name = "MyRoom" }) } if (encryptedRoom) { testHelper.waitWithLatch { latch -> val room = aliceSession.getRoom(roomId)!! - room.enableEncryption() + room.roomCryptoService().enableEncryption() val roomSummaryLive = room.getRoomSummaryLive() val roomSummaryObserver = object : Observer<Optional<RoomSummary>> { override fun onChanged(roomSummary: Optional<RoomSummary>) { @@ -98,7 +99,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { val bobSession = testHelper.createAccount(TestConstants.USER_BOB, defaultSessionParams) testHelper.waitWithLatch { latch -> - val bobRoomSummariesLive = bobSession.getRoomSummariesLive(roomSummaryQueryParams { }) + val bobRoomSummariesLive = bobSession.roomService().getRoomSummariesLive(roomSummaryQueryParams { }) val newRoomObserver = object : Observer<List<RoomSummary>> { override fun onChanged(t: List<RoomSummary>?) { if (t?.isNotEmpty() == true) { @@ -108,14 +109,15 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { } } bobRoomSummariesLive.observeForever(newRoomObserver) - aliceRoom.invite(bobSession.myUserId) + aliceRoom.membershipService().invite(bobSession.myUserId) } testHelper.waitWithLatch { latch -> - val bobRoomSummariesLive = bobSession.getRoomSummariesLive(roomSummaryQueryParams { }) + val bobRoomSummariesLive = bobSession.roomService().getRoomSummariesLive(roomSummaryQueryParams { }) val roomJoinedObserver = object : Observer<List<RoomSummary>> { override fun onChanged(t: List<RoomSummary>?) { if (bobSession.getRoom(aliceRoomId) + ?.membershipService() ?.getRoomMember(bobSession.myUserId) ?.membership == Membership.JOIN) { bobRoomSummariesLive.removeObserver(this) @@ -124,7 +126,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { } } bobRoomSummariesLive.observeForever(roomJoinedObserver) - bobSession.joinRoom(aliceRoomId) + bobSession.roomService().joinRoom(aliceRoomId) } // Ensure bob can send messages to the room // val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!! @@ -160,11 +162,11 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { val samSession = testHelper.createAccount(TestConstants.USER_SAM, defaultSessionParams) testHelper.runBlockingTest { - room.invite(samSession.myUserId, null) + room.membershipService().invite(samSession.myUserId, null) } testHelper.runBlockingTest { - samSession.joinRoom(room.roomId, null, emptyList()) + samSession.roomService().joinRoom(room.roomId, null, emptyList()) } return samSession @@ -242,8 +244,8 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { fun createDM(alice: Session, bob: Session): String { var roomId: String = "" testHelper.waitWithLatch { latch -> - roomId = alice.createDirectRoom(bob.myUserId) - val bobRoomSummariesLive = bob.getRoomSummariesLive(roomSummaryQueryParams { }) + roomId = alice.roomService().createDirectRoom(bob.myUserId) + val bobRoomSummariesLive = bob.roomService().getRoomSummariesLive(roomSummaryQueryParams { }) val newRoomObserver = object : Observer<List<RoomSummary>> { override fun onChanged(t: List<RoomSummary>?) { if (t?.any { it.roomId == roomId }.orFalse()) { @@ -256,10 +258,11 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { } testHelper.waitWithLatch { latch -> - val bobRoomSummariesLive = bob.getRoomSummariesLive(roomSummaryQueryParams { }) + val bobRoomSummariesLive = bob.roomService().getRoomSummariesLive(roomSummaryQueryParams { }) val newRoomObserver = object : Observer<List<RoomSummary>> { override fun onChanged(t: List<RoomSummary>?) { if (bob.getRoom(roomId) + ?.membershipService() ?.getRoomMember(bob.myUserId) ?.membership == Membership.JOIN) { bobRoomSummariesLive.removeObserver(this) @@ -268,7 +271,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { } } bobRoomSummariesLive.observeForever(newRoomObserver) - bob.joinRoom(roomId) + bob.roomService().joinRoom(roomId) } return roomId @@ -367,20 +370,20 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { aliceSession.cryptoService().setWarnOnUnknownDevices(false) val roomId = testHelper.runBlockingTest { - aliceSession.createRoom(CreateRoomParams().apply { name = "MyRoom" }) + aliceSession.roomService().createRoom(CreateRoomParams().apply { name = "MyRoom" }) } val room = aliceSession.getRoom(roomId)!! testHelper.runBlockingTest { - room.enableEncryption() + room.roomCryptoService().enableEncryption() } val sessions = mutableListOf(aliceSession) for (index in 1 until numberOfMembers) { val session = testHelper.createAccount("User_$index", defaultSessionParams) - testHelper.runBlockingTest(timeout = 600_000) { room.invite(session.myUserId, null) } + testHelper.runBlockingTest(timeout = 600_000) { room.membershipService().invite(session.myUserId, null) } println("TEST -> " + session.myUserId + " invited") - testHelper.runBlockingTest { session.joinRoom(room.roomId, null, emptyList()) } + testHelper.runBlockingTest { session.roomService().joinRoom(room.roomId, null, emptyList()) } println("TEST -> " + session.myUserId + " joined") sessions.add(session) } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt index 732f4f7dce28b28422d5417b8920e588b7f1c486..f5f585a1e0c9f6e4daa9194220962fc5349e8f16 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt @@ -29,8 +29,10 @@ import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileKey import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments +import org.matrix.android.sdk.internal.util.time.DefaultClock import java.io.ByteArrayOutputStream import java.io.InputStream +import java.util.UUID /** * Unit tests AttachmentEncryptionTest. @@ -48,13 +50,18 @@ class AttachmentEncryptionTest { inputStream = if (inputAsByteArray.isEmpty()) { inputAsByteArray.inputStream() } else { - val memoryFile = MemoryFile("file" + System.currentTimeMillis(), inputAsByteArray.size) + val memoryFile = MemoryFile("file_" + UUID.randomUUID(), inputAsByteArray.size) memoryFile.outputStream.write(inputAsByteArray) memoryFile.inputStream } val decryptedStream = ByteArrayOutputStream() - val result = MXEncryptedAttachments.decryptAttachment(inputStream, encryptedFileInfo.toElementToDecrypt()!!, decryptedStream) + val result = MXEncryptedAttachments.decryptAttachment( + attachmentStream = inputStream, + elementToDecrypt = encryptedFileInfo.toElementToDecrypt()!!, + outputStream = decryptedStream, + clock = DefaultClock() + ) assert(result) @@ -117,9 +124,13 @@ class AttachmentEncryptionTest { url = "dummyUrl" ) - assertEquals("YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ", - checkDecryption("zhtFStAeFx0s+9L/sSQO+WQMtldqYEHqTxMduJrCIpnkyer09kxJJuA4K+adQE4w+7jZe/vR9kIcqj9rOhDR8Q", - encryptedFileInfo)) + assertEquals( + "YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ", + checkDecryption( + "zhtFStAeFx0s+9L/sSQO+WQMtldqYEHqTxMduJrCIpnkyer09kxJJuA4K+adQE4w+7jZe/vR9kIcqj9rOhDR8Q", + encryptedFileInfo + ) + ) } @Test @@ -138,8 +149,12 @@ class AttachmentEncryptionTest { url = "dummyUrl" ) - assertNotEquals("YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ", - checkDecryption("tJVNBVJ/vl36UQt4Y5e5m84bRUrQHhcdLPvS/7EkDvlkDLZXamBB6k8THbiawiKZ5Mnq9PZMSSbgOCvmnUBOMA", - encryptedFileInfo)) + assertNotEquals( + "YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ", + checkDecryption( + "tJVNBVJ/vl36UQt4Y5e5m84bRUrQHhcdLPvS/7EkDvlkDLZXamBB6k8THbiawiKZ5Mnq9PZMSSbgOCvmnUBOMA", + encryptedFileInfo + ) + ) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt index c717c8e33fe46dc170fff63e6cbba0d7ac5f4db2..ba1afd4758a2fd68cb618943d9acc80fa136f5ff 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt @@ -22,6 +22,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.internal.util.time.DefaultClock import kotlin.random.Random internal class CryptoStoreHelper { @@ -34,7 +35,8 @@ internal class CryptoStoreHelper { .build(), crossSigningKeysMapper = CrossSigningKeysMapper(MoshiProvider.providesMoshi()), userId = "userId_" + Random.nextInt(), - deviceId = "deviceId_sample" + deviceId = "deviceId_sample", + clock = DefaultClock(), ) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt index f43c425cc9744263434ca676f096c4be6ef8aee7..3f75aa09798a476184cf35bd170a73b318e17b47 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt @@ -27,6 +27,7 @@ import org.junit.runner.RunWith import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore +import org.matrix.android.sdk.internal.util.time.DefaultClock import org.matrix.olm.OlmAccount import org.matrix.olm.OlmManager import org.matrix.olm.OlmSession @@ -37,6 +38,7 @@ private const val DUMMY_DEVICE_KEY = "DeviceKey" class CryptoStoreTest : InstrumentedTest { private val cryptoStoreHelper = CryptoStoreHelper() + private val clock = DefaultClock() @Before fun setup() { @@ -106,7 +108,7 @@ class CryptoStoreTest : InstrumentedTest { // Note: we cannot be sure what will be the result of getLastUsedSessionId() here - olmSessionWrapper2.onMessageReceived() + olmSessionWrapper2.onMessageReceived(clock.epochMillis()) cryptoStore.storeSession(olmSessionWrapper2, DUMMY_DEVICE_KEY) // sessionId2 is returned now @@ -114,7 +116,7 @@ class CryptoStoreTest : InstrumentedTest { Thread.sleep(2) - olmSessionWrapper1.onMessageReceived() + olmSessionWrapper1.onMessageReceived(clock.epochMillis()) cryptoStore.storeSession(olmSessionWrapper1, DUMMY_DEVICE_KEY) // sessionId1 is returned now diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt index 388468315109a9ea2b2350476a92c5a3327c9836..88d99f12e062237540b28fed1cff3ae2e952a176 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt @@ -38,8 +38,11 @@ import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom +import org.matrix.android.sdk.api.session.getRoomSummary import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.failure.JoinRoomFailure +import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.send.SendState @@ -86,7 +89,7 @@ class E2eeSanityTests : InstrumentedTest { otherAccounts.forEach { testHelper.runBlockingTest { Log.v("#E2E TEST", "Alice invites ${it.myUserId}") - aliceRoomPOV.invite(it.myUserId) + aliceRoomPOV.membershipService().invite(it.myUserId) } } @@ -128,7 +131,7 @@ class E2eeSanityTests : InstrumentedTest { newAccount.forEach { testHelper.runBlockingTest { Log.v("#E2E TEST", "Alice invites ${it.myUserId}") - aliceRoomPOV.invite(it.myUserId) + aliceRoomPOV.membershipService().invite(it.myUserId) } } @@ -523,10 +526,10 @@ class E2eeSanityTests : InstrumentedTest { } private fun sendMessageInRoom(aliceRoomPOV: Room, text: String): String? { - aliceRoomPOV.sendTextMessage(text) + aliceRoomPOV.sendService().sendTextMessage(text) var sentEventId: String? = null testHelper.waitWithLatch(4 * TestConstants.timeOutMillis) { latch -> - val timeline = aliceRoomPOV.createTimeline(null, TimelineSettings(60)) + val timeline = aliceRoomPOV.timelineService().createTimeline(null, TimelineSettings(60)) timeline.start() testHelper.retryPeriodicallyWithLatch(latch) { @@ -551,7 +554,7 @@ class E2eeSanityTests : InstrumentedTest { testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { otherAccounts.map { - aliceSession.getRoomMember(it.myUserId, e2eRoomID)?.membership + aliceSession.roomService().getRoomMember(it.myUserId, e2eRoomID)?.membership }.all { it == Membership.JOIN } @@ -574,7 +577,7 @@ class E2eeSanityTests : InstrumentedTest { testHelper.runBlockingTest(60_000) { Log.v("#E2E TEST", "${otherSession.myUserId} tries to join room $e2eRoomID") try { - otherSession.joinRoom(e2eRoomID) + otherSession.roomService().joinRoom(e2eRoomID) } catch (ex: JoinRoomFailure.JoinedWithTimeout) { // it's ok we will wait after } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt index aa9f09314fdd4a6a13c23dd0731484ff8213173c..8a1edec5e3dcd9448998992fa801b3f952accac2 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt @@ -29,6 +29,8 @@ import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom +import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt index 83464305307c15eab276deed8b1a77960b5e21ac..de4a928dc36f4bedfb079b8cf6c99a05666b1669 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt @@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings @@ -97,7 +98,7 @@ class UnwedgingTest : InstrumentedTest { val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!! val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!! - val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(20)) + val bobTimeline = roomFromBobPOV.timelineService().createTimeline(null, TimelineSettings(20)) bobTimeline.start() val bobFinalLatch = CountDownLatch(1) @@ -128,7 +129,7 @@ class UnwedgingTest : InstrumentedTest { messagesReceivedByBob = emptyList() // - Alice sends a 1st message with a 1st megolm session - roomFromAlicePOV.sendTextMessage("First message") + roomFromAlicePOV.sendService().sendTextMessage("First message") // Wait for the message to be received by Bob testHelper.await(latch) @@ -156,7 +157,7 @@ class UnwedgingTest : InstrumentedTest { Timber.i("## CRYPTO | testUnwedging: Alice sends a 2nd message with a 2nd megolm session") // - Alice sends a 2nd message with a 2nd megolm session - roomFromAlicePOV.sendTextMessage("Second message") + roomFromAlicePOV.sendService().sendTextMessage("Second message") // Wait for the message to be received by Bob testHelper.await(latch) @@ -185,7 +186,7 @@ class UnwedgingTest : InstrumentedTest { Timber.i("## CRYPTO | testUnwedging: Alice sends a 3rd message with a 3rd megolm session but a wedged olm session") // - Alice sends a 3rd message with a 3rd megolm session but a wedged olm session - roomFromAlicePOV.sendTextMessage("Third message") + roomFromAlicePOV.sendService().sendTextMessage("Third message") // Bob should not be able to decrypt, because the session key could not be sent } bobTimeline.removeListener(bobEventsListener) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt index dc65cec187b088732b259e56b5f188a24bf7c87b..0f3ff7898fd357c3ceada6d94f14cb873274fe7f 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt @@ -110,11 +110,13 @@ class XSigningTest : InstrumentedTest { } }, it) } - testHelper.doSync<Unit> { bobSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { - override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { - promise.resume(bobAuthParams) - } - }, it) } + testHelper.doSync<Unit> { + bobSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { + override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { + promise.resume(bobAuthParams) + } + }, it) + } // Check that alice can see bob keys testHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> { aliceSession.cryptoService().downloadKeys(listOf(bobSession.myUserId), true, it) } @@ -149,16 +151,20 @@ class XSigningTest : InstrumentedTest { password = TestConstants.PASSWORD ) - testHelper.doSync<Unit> { aliceSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { - override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { - promise.resume(aliceAuthParams) - } - }, it) } - testHelper.doSync<Unit> { bobSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { - override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { - promise.resume(bobAuthParams) - } - }, it) } + testHelper.doSync<Unit> { + aliceSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { + override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { + promise.resume(aliceAuthParams) + } + }, it) + } + testHelper.doSync<Unit> { + bobSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { + override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { + promise.resume(bobAuthParams) + } + }, it) + } // Check that alice can see bob keys val bobUserId = bobSession.myUserId diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt index 84c9487e030a27eeeeae5d325ea3b8a984d067bb..85b6c21df37ea2744e84c86b29cbe9a8c89f036d 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt @@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.timeline.Timeline @@ -48,7 +49,7 @@ class EncryptionTest : InstrumentedTest { fun test_EncryptionEvent() { performTest(roomShouldBeEncrypted = false) { room -> // Send an encryption Event as an Event (and not as a state event) - room.sendEvent( + room.sendService().sendEvent( eventType = EventType.STATE_ROOM_ENCRYPTION, content = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent() ) @@ -60,7 +61,7 @@ class EncryptionTest : InstrumentedTest { performTest(roomShouldBeEncrypted = true) { room -> runBlocking { // Send an encryption Event as a State Event - room.sendStateEvent( + room.stateService().sendStateEvent( eventType = EventType.STATE_ROOM_ENCRYPTION, stateKey = "", body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent() @@ -75,9 +76,9 @@ class EncryptionTest : InstrumentedTest { val aliceSession = cryptoTestData.firstSession val room = aliceSession.getRoom(cryptoTestData.roomId)!! - room.isEncrypted() shouldBe false + room.roomCryptoService().isEncrypted() shouldBe false - val timeline = room.createTimeline(null, TimelineSettings(10)) + val timeline = room.timelineService().createTimeline(null, TimelineSettings(10)) val latch = CountDownLatch(1) val timelineListener = object : Timeline.Listener { override fun onTimelineFailure(throwable: Throwable) { @@ -105,7 +106,7 @@ class EncryptionTest : InstrumentedTest { testHelper.await(latch) timeline.dispose() testHelper.waitWithLatch { - room.isEncrypted() shouldBe roomShouldBeEncrypted + room.roomCryptoService().isEncrypted() shouldBe roomShouldBeEncrypted it.countDown() } cryptoTestData.cleanUp(testHelper) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt index 5e271c6910180bc4a390d9797034499d0e9bd0f5..592d24fb690650338a44e8e166cb93aee72a29e0 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt @@ -50,6 +50,8 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransa import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom +import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.model.message.MessageContent @@ -73,7 +75,7 @@ class KeyShareTests : InstrumentedTest { // Create an encrypted room and add a message val roomId = commonTestHelper.runBlockingTest { - aliceSession.createRoom( + aliceSession.roomService().createRoom( CreateRoomParams().apply { visibility = RoomDirectoryVisibility.PRIVATE enableEncryption() @@ -83,7 +85,7 @@ class KeyShareTests : InstrumentedTest { val room = aliceSession.getRoom(roomId) assertNotNull(room) Thread.sleep(4_000) - assertTrue(room?.isEncrypted() == true) + assertTrue(room?.roomCryptoService()?.isEncrypted() == true) val sentEventId = commonTestHelper.sendTextMessage(room!!, "My Message", 1).first().eventId // Open a new sessionx @@ -340,7 +342,7 @@ class KeyShareTests : InstrumentedTest { // Create an encrypted room and send a couple of messages val roomId = commonTestHelper.runBlockingTest { - aliceSession.createRoom( + aliceSession.roomService().createRoom( CreateRoomParams().apply { visibility = RoomDirectoryVisibility.PRIVATE enableEncryption() @@ -350,7 +352,7 @@ class KeyShareTests : InstrumentedTest { val roomAlicePov = aliceSession.getRoom(roomId) assertNotNull(roomAlicePov) Thread.sleep(1_000) - assertTrue(roomAlicePov?.isEncrypted() == true) + assertTrue(roomAlicePov?.roomCryptoService()?.isEncrypted() == true) val secondEventId = commonTestHelper.sendTextMessage(roomAlicePov!!, "Message", 3)[1].eventId // Create bob session @@ -374,11 +376,11 @@ class KeyShareTests : InstrumentedTest { // Let alice invite bob commonTestHelper.runBlockingTest { - roomAlicePov.invite(bobSession.myUserId, null) + roomAlicePov.membershipService().invite(bobSession.myUserId, null) } commonTestHelper.runBlockingTest { - bobSession.joinRoom(roomAlicePov.roomId, null, emptyList()) + bobSession.roomService().joinRoom(roomAlicePov.roomId, null, emptyList()) } // we want to discard alice outbound session diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt index 55bb03278c77b8bf8de0b11343f6761a7682c36c..bad9fd0f68775a6618767cff21546cf059e96f73 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt @@ -33,6 +33,8 @@ import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom +import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.MockOkHttpInterceptor diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt index 063c0c0ca397310a442a9eefb0d93a23893ae6a8..3220f161fa499a131b968baff01631372cdf11c0 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt @@ -41,6 +41,7 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.TestConstants diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt index d6baa4b1e0d42430ec79bb91c295b6284bf4d576..a882f690132c3da214982a50d10f8150e7f79675 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt @@ -60,7 +60,7 @@ class QuadSTests : InstrumentedTest { val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) - val quadS = aliceSession.sharedSecretStorageService + val quadS = aliceSession.sharedSecretStorageService() val TEST_KEY_ID = "my.test.Key" @@ -120,7 +120,7 @@ class QuadSTests : InstrumentedTest { // Store a secret val clearSecret = "42".toByteArray().toBase64NoPadding() testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService.storeSecret( + aliceSession.sharedSecretStorageService().storeSecret( "secret.of.life", clearSecret, listOf(SharedSecretStorageService.KeyRef(null, keySpec)) // default key @@ -141,7 +141,7 @@ class QuadSTests : InstrumentedTest { // Try to decrypt?? val decryptedSecret = testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService.getSecret( + aliceSession.sharedSecretStorageService().getSecret( "secret.of.life", null, // default key keySpec!! @@ -158,7 +158,7 @@ class QuadSTests : InstrumentedTest { val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) - val quadS = aliceSession.sharedSecretStorageService + val quadS = aliceSession.sharedSecretStorageService() val TEST_KEY_ID = "my.test.Key" @@ -187,7 +187,7 @@ class QuadSTests : InstrumentedTest { val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit" testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService.storeSecret( + aliceSession.sharedSecretStorageService().storeSecret( "my.secret", mySecretText.toByteArray().toBase64NoPadding(), listOf( @@ -207,14 +207,14 @@ class QuadSTests : InstrumentedTest { // Assert that can decrypt with both keys testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService.getSecret("my.secret", + aliceSession.sharedSecretStorageService().getSecret("my.secret", keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)!! ) } testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService.getSecret("my.secret", + aliceSession.sharedSecretStorageService().getSecret("my.secret", keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)!! ) @@ -236,7 +236,7 @@ class QuadSTests : InstrumentedTest { val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit" testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService.storeSecret( + aliceSession.sharedSecretStorageService().storeSecret( "my.secret", mySecretText.toByteArray().toBase64NoPadding(), listOf(SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey))) @@ -245,7 +245,7 @@ class QuadSTests : InstrumentedTest { testHelper.runBlockingTest { try { - aliceSession.sharedSecretStorageService.getSecret("my.secret", + aliceSession.sharedSecretStorageService().getSecret("my.secret", keyId1, RawBytesKeySpec.fromPassphrase( "A bad passphrase", @@ -260,7 +260,7 @@ class QuadSTests : InstrumentedTest { // Now try with correct key testHelper.runBlockingTest { - aliceSession.sharedSecretStorageService.getSecret("my.secret", + aliceSession.sharedSecretStorageService().getSecret("my.secret", keyId1, RawBytesKeySpec.fromPassphrase( passphrase, @@ -292,7 +292,7 @@ class QuadSTests : InstrumentedTest { } private fun generatedSecret(session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo { - val quadS = session.sharedSecretStorageService + val quadS = session.sharedSecretStorageService() val testHelper = CommonTestHelper(context()) val creationInfo = testHelper.runBlockingTest { @@ -312,7 +312,7 @@ class QuadSTests : InstrumentedTest { } private fun generatedSecretFromPassphrase(session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo { - val quadS = session.sharedSecretStorageService + val quadS = session.sharedSecretStorageService() val testHelper = CommonTestHelper(context()) val creationInfo = testHelper.runBlockingTest { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt index 2c96568102904016eafb7439c897c9cf87011eee..374d709505311572790f0019f01d2b8dddadde79 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/VerificationTest.kt @@ -155,8 +155,8 @@ class VerificationTest : InstrumentedTest { bobSupportedMethods: List<VerificationMethod>, expectedResultForAlice: ExpectedResult, expectedResultForBob: ExpectedResult) { - val testHelper = CommonTestHelper(context()) - val cryptoTestHelper = CryptoTestHelper(testHelper) + val testHelper = CommonTestHelper(context()) + val cryptoTestHelper = CryptoTestHelper(testHelper) val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val aliceSession = cryptoTestData.firstSession diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt index dcb181f0c1e498fbec597b0c7f0e51346234dcbb..f6e08a576e20b3fcf29a88f2689ec05d6bd635cc 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/threads/ThreadMessagingTest.kt @@ -31,6 +31,7 @@ import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.events.model.getRootThreadEventId import org.matrix.android.sdk.api.session.events.model.isTextMessage import org.matrix.android.sdk.api.session.events.model.isThread +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.common.CommonTestHelper @@ -80,7 +81,7 @@ class ThreadMessagingTest : InstrumentedTest { replyInThread.root.getRootThreadEventId().shouldBeEqualTo(initMessage.root.eventId) // The init normal message should now be a root thread event - val timeline = aliceRoom.createTimeline(null, TimelineSettings(30)) + val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30)) timeline.start() aliceSession.startSync(true) @@ -141,7 +142,7 @@ class ThreadMessagingTest : InstrumentedTest { replyInThread.root.getRootThreadEventId().shouldBeEqualTo(initMessage.root.eventId) // The init normal message should now be a root thread event - val timeline = aliceRoom.createTimeline(null, TimelineSettings(30)) + val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30)) timeline.start() aliceSession.startSync(true) @@ -214,7 +215,7 @@ class ThreadMessagingTest : InstrumentedTest { } // The init normal message should now be a root thread event - val timeline = aliceRoom.createTimeline(null, TimelineSettings(30)) + val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30)) timeline.start() aliceSession.startSync(true) @@ -309,7 +310,7 @@ class ThreadMessagingTest : InstrumentedTest { } // The init normal message should now be a root thread event - val timeline = aliceRoom.createTimeline(null, TimelineSettings(30)) + val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30)) timeline.start() aliceSession.startSync(true) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt index 5c011c8b2fb195711e3afe55bc2f31b389912573..27d3fdc85615fe8e106ac69868560b04322ab088 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt @@ -35,6 +35,7 @@ import org.matrix.android.sdk.internal.database.mapper.toEntity import org.matrix.android.sdk.internal.database.model.ChunkEntity import org.matrix.android.sdk.internal.database.model.SessionRealmModule import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection +import org.matrix.android.sdk.internal.util.time.DefaultClock import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeListOfEvents import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeMessageEvent @@ -42,6 +43,7 @@ import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeMes internal class ChunkEntityTest : InstrumentedTest { private lateinit var monarchy: Monarchy + private val clock = DefaultClock() @Before fun setup() { @@ -59,7 +61,7 @@ internal class ChunkEntityTest : InstrumentedTest { monarchy.runTransactionSync { realm -> val chunk: ChunkEntity = realm.createObject() - val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, System.currentTimeMillis()).let { + val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, clock.epochMillis()).let { realm.copyToRealm(it) } chunk.addTimelineEvent( @@ -75,7 +77,7 @@ internal class ChunkEntityTest : InstrumentedTest { fun add_shouldNotAdd_whenAlreadyIncluded() { monarchy.runTransactionSync { realm -> val chunk: ChunkEntity = realm.createObject() - val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, System.currentTimeMillis()).let { + val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, clock.epochMillis()).let { realm.copyToRealm(it) } chunk.addTimelineEvent( @@ -153,7 +155,7 @@ internal class ChunkEntityTest : InstrumentedTest { events: List<Event>, direction: PaginationDirection) { events.forEach { event -> - val fakeEvent = event.toEntity(roomId, SendState.SYNCED, System.currentTimeMillis()).let { + val fakeEvent = event.toEntity(roomId, SendState.SYNCED, clock.epochMillis()).let { realm.copyToRealm(it) } addTimelineEvent( diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeGetContextOfEventTask.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeGetContextOfEventTask.kt index b86c86c0c7179c92f0498712dbfd83490e046128..ccf1c7c2c9410fd5559d6de54ab51d69361a9489 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeGetContextOfEventTask.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeGetContextOfEventTask.kt @@ -26,8 +26,8 @@ internal class FakeGetContextOfEventTask constructor(private val tokenChunkEvent override suspend fun execute(params: GetContextOfEventTask.Params): TokenChunkEventPersistor.Result { val fakeEvents = RoomDataHelper.createFakeListOfEvents(30) val tokenChunkEvent = FakeTokenChunkEvent( - Random.nextLong(System.currentTimeMillis()).toString(), - Random.nextLong(System.currentTimeMillis()).toString(), + Random.nextLong().toString(), + Random.nextLong().toString(), fakeEvents ) return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, PaginationDirection.BACKWARDS) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakePaginationTask.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakePaginationTask.kt index d09bfb18c6c6949e03d637577d43a548652dfea4..f241be0c5c90054fdfbd33ef3b8e12ed28250783 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakePaginationTask.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakePaginationTask.kt @@ -25,7 +25,7 @@ internal class FakePaginationTask @Inject constructor(private val tokenChunkEven override suspend fun execute(params: PaginationTask.Params): TokenChunkEventPersistor.Result { val fakeEvents = RoomDataHelper.createFakeListOfEvents(30) - val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong(System.currentTimeMillis()).toString(), fakeEvents) + val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong().toString(), fakeEvents) return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt index 6792d6ddfd039024870c2434b36cd2efb32b3399..61ab6d4b40f301673ac6c32c804f6875ff6e8513 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/PollAggregationTest.kt @@ -30,6 +30,7 @@ import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.model.PollResponseAggregatedSummary import org.matrix.android.sdk.api.session.room.model.PollSummaryContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent @@ -57,10 +58,10 @@ class PollAggregationTest : InstrumentedTest { val roomFromBobPOV = cryptoTestData.secondSession!!.getRoom(cryptoTestData.roomId)!! // Bob creates a poll - roomFromBobPOV.sendPoll(PollType.DISCLOSED, pollQuestion, pollOptions) + roomFromBobPOV.sendService().sendPoll(PollType.DISCLOSED, pollQuestion, pollOptions) aliceSession.startSync(true) - val aliceTimeline = roomFromAlicePOV.createTimeline(null, TimelineSettings(30)) + val aliceTimeline = roomFromAlicePOV.timelineService().createTimeline(null, TimelineSettings(30)) aliceTimeline.start() val TOTAL_TEST_COUNT = 7 @@ -83,37 +84,37 @@ class PollAggregationTest : InstrumentedTest { // Poll has just been created. testInitialPollConditions(pollContent, pollSummary) lock.countDown() - roomFromBobPOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.firstOrNull()?.id ?: "") + roomFromBobPOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.firstOrNull()?.id ?: "") } TOTAL_TEST_COUNT - 1 -> { // Bob: Option 1 testBobVotesOption1(pollContent, pollSummary) lock.countDown() - roomFromBobPOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "") + roomFromBobPOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "") } TOTAL_TEST_COUNT - 2 -> { // Bob: Option 2 testBobChangesVoteToOption2(pollContent, pollSummary) lock.countDown() - roomFromAlicePOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "") + roomFromAlicePOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "") } TOTAL_TEST_COUNT - 3 -> { // Alice: Option 2, Bob: Option 2 testAliceAndBobVoteToOption2(pollContent, pollSummary) lock.countDown() - roomFromAlicePOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.firstOrNull()?.id ?: "") + roomFromAlicePOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.firstOrNull()?.id ?: "") } TOTAL_TEST_COUNT - 4 -> { // Alice: Option 1, Bob: Option 2 testAliceVotesOption1AndBobVotesOption2(pollContent, pollSummary) lock.countDown() - roomFromBobPOV.endPoll(pollEventId) + roomFromBobPOV.sendService().endPoll(pollEventId) } TOTAL_TEST_COUNT - 5 -> { // Alice: Option 1, Bob: Option 2 [poll is ended] testEndedPoll(pollSummary) lock.countDown() - roomFromAlicePOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "") + roomFromAlicePOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "") } TOTAL_TEST_COUNT - 6 -> { // Alice: Option 1 (ignore change), Bob: Option 2 [poll is ended] diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt index ee44af58b305549f000b3cba5d6c7a96bb5a0c24..3864ea1cd1b28941f485677c719e2deff006a6af 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt @@ -30,6 +30,7 @@ import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings @@ -74,7 +75,7 @@ class TimelineForwardPaginationTest : InstrumentedTest { // Alice clear the cache and restart the sync commonTestHelper.clearCacheAndSync(aliceSession) - val aliceTimeline = roomFromAlicePOV.createTimeline(null, TimelineSettings(30)) + val aliceTimeline = roomFromAlicePOV.timelineService().createTimeline(null, TimelineSettings(30)) aliceTimeline.start() // Alice sees the 10 last message of the room, and can only navigate BACKWARD diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt index c6d40bcaa26d1effe5c3415b96aed9b6b1a31b4b..5d09b74e6c3f8773ef10ffea907996418dfd8524 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt @@ -28,6 +28,7 @@ import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings @@ -62,7 +63,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest { val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!! val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!! - val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(30)) + val bobTimeline = roomFromBobPOV.timelineService().createTimeline(null, TimelineSettings(30)) bobTimeline.start() run { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt index 53f76f1c46c2181b5eba816f62f10dd22b81c18b..251b2c614cd7302c1738fb7ba7ee86f0506b5df8 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineSimpleBackPaginationTest.kt @@ -28,6 +28,7 @@ import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.events.model.isTextMessage import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings @@ -65,7 +66,7 @@ class TimelineSimpleBackPaginationTest : InstrumentedTest { message, numberOfMessagesToSent) - val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(30)) + val bobTimeline = roomFromBobPOV.timelineService().createTimeline(null, TimelineSettings(30)) bobTimeline.start() commonTestHelper.waitWithLatch(timeout = TestConstants.timeOutMillis * 10) { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt index ce02b2b527e89898b926e54ec7b16b81c219849c..02430dda745a541292cdcb9f079c2b328504846c 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineWithManyMembersTest.kt @@ -27,6 +27,7 @@ import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.common.CommonTestHelper @@ -71,7 +72,7 @@ class TimelineWithManyMembersTest : InstrumentedTest { for (index in 1 until cryptoTestData.sessions.size) { val session = cryptoTestData.sessions[index] val roomForCurrentMember = session.getRoom(cryptoTestData.roomId)!! - val timelineForCurrentMember = roomForCurrentMember.createTimeline(null, TimelineSettings(30)) + val timelineForCurrentMember = roomForCurrentMember.timelineService().createTimeline(null, TimelineSettings(30)) timelineForCurrentMember.start() session.startSync(true) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt index fa07cf5a02c07587f1d70725b8034c6a97c7d410..ab0bbe7f73f9450fc913577e3f3c1c417bbb93de 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/search/SearchMessagesTest.kt @@ -24,6 +24,7 @@ import org.junit.runners.JUnit4 import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.extensions.orFalse +import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.search.SearchResult import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestData @@ -59,9 +60,10 @@ class SearchMessagesTest : InstrumentedTest { fun sendTextMessageAndSearchPartOfItUsingRoom() { doTest { cryptoTestData -> cryptoTestData.firstSession - .getRoom(cryptoTestData.roomId)!! + .searchService() .search( searchTerm = "lore", + roomId = cryptoTestData.roomId, limit = 10, includeProfile = true, afterLimit = 0, diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt index 3b0f7586ccfd571d97c2c0c8887495f44420480e..b9760c1bfc73f57903a33e04900ae8ddac92d080 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt @@ -29,6 +29,7 @@ import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.getStateEvent import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent @@ -147,7 +148,7 @@ class SpaceCreationTest : InstrumentedTest { // create a room var firstChild: String? = null commonTestHelper.waitWithLatch { - firstChild = aliceSession.createRoom(CreateRoomParams().apply { + firstChild = aliceSession.roomService().createRoom(CreateRoomParams().apply { this.name = "FirstRoom" this.topic = "Description of first room" this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT @@ -162,7 +163,7 @@ class SpaceCreationTest : InstrumentedTest { var secondChild: String? = null commonTestHelper.waitWithLatch { - secondChild = aliceSession.createRoom(CreateRoomParams().apply { + secondChild = aliceSession.roomService().createRoom(CreateRoomParams().apply { this.name = "SecondRoom" this.topic = "Description of second room" this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt index 50e4a6feb6d7c1af67c28122af82cce790165d73..d2c8b52fc7693ac08e1eab3c4c7e9b953a2395ab 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt @@ -35,6 +35,9 @@ import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.getRoom +import org.matrix.android.sdk.api.session.getRoomSummary +import org.matrix.android.sdk.api.session.room.getStateEvent import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -68,7 +71,7 @@ class SpaceHierarchyTest : InstrumentedTest { var roomId = "" commonTestHelper.waitWithLatch { - roomId = session.createRoom(CreateRoomParams().apply { name = "General" }) + roomId = session.roomService().createRoom(CreateRoomParams().apply { name = "General" }) it.countDown() } @@ -203,27 +206,27 @@ class SpaceHierarchyTest : InstrumentedTest { var orphan1 = "" commonTestHelper.waitWithLatch { - orphan1 = session.createRoom(CreateRoomParams().apply { name = "O1" }) + orphan1 = session.roomService().createRoom(CreateRoomParams().apply { name = "O1" }) it.countDown() } var orphan2 = "" commonTestHelper.waitWithLatch { - orphan2 = session.createRoom(CreateRoomParams().apply { name = "O2" }) + orphan2 = session.roomService().createRoom(CreateRoomParams().apply { name = "O2" }) it.countDown() } - val allRooms = session.getRoomSummaries(roomSummaryQueryParams { excludeType = listOf(RoomType.SPACE) }) + val allRooms = session.roomService().getRoomSummaries(roomSummaryQueryParams { excludeType = listOf(RoomType.SPACE) }) assertEquals("Unexpected number of rooms", 9, allRooms.size) - val orphans = session.getFlattenRoomSummaryChildrenOf(null) + val orphans = session.roomService().getFlattenRoomSummaryChildrenOf(null) assertEquals("Unexpected number of orphan rooms", 2, orphans.size) assertTrue("O1 should be an orphan", orphans.any { it.roomId == orphan1 }) assertTrue("O2 should be an orphan ${orphans.map { it.name }}", orphans.any { it.roomId == orphan2 }) - val aChildren = session.getFlattenRoomSummaryChildrenOf(spaceAInfo.spaceId) + val aChildren = session.roomService().getFlattenRoomSummaryChildrenOf(spaceAInfo.spaceId) assertEquals("Unexpected number of flatten child rooms", 4, aChildren.size) assertTrue("A1 should be a child of A", aChildren.any { it.name == "A1" }) @@ -233,13 +236,13 @@ class SpaceHierarchyTest : InstrumentedTest { // Add a non canonical child and check that it does not appear as orphan commonTestHelper.waitWithLatch { - val a3 = session.createRoom(CreateRoomParams().apply { name = "A3" }) + val a3 = session.roomService().createRoom(CreateRoomParams().apply { name = "A3" }) spaceA!!.addChildren(a3, viaServers, null, false) it.countDown() } Thread.sleep(6_000) - val orphansUpdate = session.getRoomSummaries(roomSummaryQueryParams { + val orphansUpdate = session.roomService().getRoomSummaries(roomSummaryQueryParams { activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(null) }) assertEquals("Unexpected number of orphan rooms ${orphansUpdate.map { it.name }}", 2, orphansUpdate.size) @@ -279,7 +282,7 @@ class SpaceHierarchyTest : InstrumentedTest { // A -> C -> A - val aChildren = session.getFlattenRoomSummaryChildrenOf(spaceAInfo.spaceId) + val aChildren = session.roomService().getFlattenRoomSummaryChildrenOf(spaceAInfo.spaceId) assertEquals("Unexpected number of flatten child rooms ${aChildren.map { it.name }}", 4, aChildren.size) assertTrue("A1 should be a child of A", aChildren.any { it.name == "A1" }) @@ -319,7 +322,7 @@ class SpaceHierarchyTest : InstrumentedTest { commonTestHelper.waitWithLatch { latch -> - val flatAChildren = session.getFlattenRoomSummaryChildrenOfLive(spaceAInfo.spaceId) + val flatAChildren = session.roomService().getFlattenRoomSummaryChildrenOfLive(spaceAInfo.spaceId) val childObserver = object : Observer<List<RoomSummary>> { override fun onChanged(children: List<RoomSummary>?) { // Log.d("## TEST", "Space A flat children update : ${children?.map { it.name }}") @@ -346,7 +349,7 @@ class SpaceHierarchyTest : InstrumentedTest { val bRoomId = spaceBInfo.roomIds.first() commonTestHelper.waitWithLatch { latch -> - val flatAChildren = session.getFlattenRoomSummaryChildrenOfLive(spaceAInfo.spaceId) + val flatAChildren = session.roomService().getFlattenRoomSummaryChildrenOfLive(spaceAInfo.spaceId) val childObserver = object : Observer<List<RoomSummary>> { override fun onChanged(children: List<RoomSummary>?) { System.out.println("## TEST | Space A flat children update : ${children?.map { it.name }}") @@ -359,7 +362,7 @@ class SpaceHierarchyTest : InstrumentedTest { } // part from b room - session.leaveRoom(bRoomId) + session.roomService().leaveRoom(bRoomId) // The room should have disapear from flat children flatAChildren.observeForever(childObserver) } @@ -385,7 +388,7 @@ class SpaceHierarchyTest : InstrumentedTest { val viaServers = listOf(session.sessionParams.homeServerHost ?: "") roomIds = childInfo.map { entry -> - session.createRoom(CreateRoomParams().apply { name = entry.first }) + session.roomService().createRoom(CreateRoomParams().apply { name = entry.first }) } roomIds.forEachIndexed { index, roomId -> syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second) @@ -414,8 +417,9 @@ class SpaceHierarchyTest : InstrumentedTest { roomIds = childInfo.map { entry -> val homeServerCapabilities = session + .homeServerCapabilitiesService() .getHomeServerCapabilities() - session.createRoom(CreateRoomParams().apply { + session.roomService().createRoom(CreateRoomParams().apply { name = entry.first this.featurePreset = RestrictedRoomPreset( homeServerCapabilities, @@ -496,22 +500,22 @@ class SpaceHierarchyTest : InstrumentedTest { )) commonTestHelper.runBlockingTest { - aliceSession.getRoom(spaceAInfo.spaceId)!!.invite(bobSession.myUserId, null) + aliceSession.getRoom(spaceAInfo.spaceId)!!.membershipService().invite(bobSession.myUserId, null) } commonTestHelper.runBlockingTest { - bobSession.joinRoom(spaceAInfo.spaceId, null, emptyList()) + bobSession.roomService().joinRoom(spaceAInfo.spaceId, null, emptyList()) } var bobRoomId = "" commonTestHelper.waitWithLatch { - bobRoomId = bobSession.createRoom(CreateRoomParams().apply { name = "A Bob Room" }) - bobSession.getRoom(bobRoomId)!!.invite(aliceSession.myUserId) + bobRoomId = bobSession.roomService().createRoom(CreateRoomParams().apply { name = "A Bob Room" }) + bobSession.getRoom(bobRoomId)!!.membershipService().invite(aliceSession.myUserId) it.countDown() } commonTestHelper.runBlockingTest { - aliceSession.joinRoom(bobRoomId) + aliceSession.roomService().joinRoom(bobRoomId) } commonTestHelper.waitWithLatch { latch -> @@ -551,7 +555,7 @@ class SpaceHierarchyTest : InstrumentedTest { ?.setUserPowerLevel(aliceSession.myUserId, Role.Admin.value) ?.toContent() - room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent!!) + room.stateService().sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent!!) it.countDown() } diff --git a/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt b/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt index 3add757efadf3b3d0577b7493b4377e679f8a80c..6dd3553d02c06d3867bfa465e4d980a923a6d7cd 100644 --- a/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt +++ b/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt @@ -37,7 +37,7 @@ import javax.inject.Inject */ @MatrixScope internal class CurlLoggingInterceptor @Inject constructor() : - Interceptor { + Interceptor { /** * Set any additional curl command options (see 'curl --help'). diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt index e7b4b766adefd743132b539abc8eeb8165461890..217f7e3da81361100540b2baa43f25eb16b2b13f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt @@ -43,7 +43,8 @@ import javax.inject.Inject /** * This is the main entry point to the matrix sdk. - * To get the singleton instance, use getInstance static method. + * <br/> + * See [Companion.createInstance] to create an instance. The app should create and manage the instance itself. */ class Matrix private constructor(context: Context, matrixConfiguration: MatrixConfiguration) { @@ -74,9 +75,7 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo fun getUserAgent() = userAgentHolder.userAgent - fun authenticationService(): AuthenticationService { - return authenticationService - } + fun authenticationService() = authenticationService fun rawService() = rawService @@ -84,9 +83,7 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo fun homeServerHistoryService() = homeServerHistoryService - fun legacySessionImporter(): LegacySessionImporter { - return legacySessionImporter - } + fun legacySessionImporter() = legacySessionImporter fun workerFactory(): WorkerFactory = matrixWorkerFactory @@ -143,6 +140,9 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo return instance } + /** + * @return a String with details about the Matrix SDK version + */ fun getSdkVersion(): String { return BuildConfig.SDK_VERSION + " (" + BuildConfig.GIT_SDK_REVISION + ")" } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/UrlAndName.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/UrlAndName.kt new file mode 100644 index 0000000000000000000000000000000000000000..ca0123b8328155d66a921ee4848e8cdb085c5452 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/UrlAndName.kt @@ -0,0 +1,22 @@ +/* + * 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.api.auth + +data class UrlAndName( + val url: String, + val name: String +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt new file mode 100644 index 0000000000000000000000000000000000000000..1a4c1ee51ce4fc0cb8a721c0752cc165eba2c2c5 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/converter.kt @@ -0,0 +1,127 @@ +/* + * 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.api.auth + +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms +import org.matrix.android.sdk.api.auth.registration.TermPolicies + +/** + * This method extract the policies from the login terms parameter, regarding the user language. + * For each policy, if user language is not found, the default language is used and if not found, the first url and name are used (not predictable) + * + * Example of Data: + * <pre> + * "m.login.terms": { + * "policies": { + * "privacy_policy": { + * "version": "1.0", + * "en": { + * "url": "http:\/\/matrix.org\/_matrix\/consent?v=1.0", + * "name": "Terms and Conditions" + * } + * } + * } + * } + *</pre> + * + * @param userLanguage the user language + * @param defaultLanguage the default language to use if the user language is not found for a policy in registrationFlowResponse + */ +fun TermPolicies.toLocalizedLoginTerms(userLanguage: String, + defaultLanguage: String = "en"): List<LocalizedFlowDataLoginTerms> { + val result = ArrayList<LocalizedFlowDataLoginTerms>() + + val policies = get("policies") + if (policies is Map<*, *>) { + policies.keys.forEach { policyName -> + val localizedFlowDataLoginTermsPolicyName = policyName as String + var localizedFlowDataLoginTermsVersion: String? = null + var localizedFlowDataLoginTermsLocalizedUrl: String? = null + var localizedFlowDataLoginTermsLocalizedName: String? = null + + val policy = policies[policyName] + + // Enter this policy + if (policy is Map<*, *>) { + // Version + localizedFlowDataLoginTermsVersion = policy["version"] as String? + + var userLanguageUrlAndName: UrlAndName? = null + var defaultLanguageUrlAndName: UrlAndName? = null + var firstUrlAndName: UrlAndName? = null + + // Search for language + policy.keys.forEach { policyKey -> + when (policyKey) { + "version" -> Unit // Ignore + userLanguage -> { + // We found the data for the user language + userLanguageUrlAndName = extractUrlAndName(policy[policyKey]) + } + defaultLanguage -> { + // We found default language + defaultLanguageUrlAndName = extractUrlAndName(policy[policyKey]) + } + else -> { + if (firstUrlAndName == null) { + // Get at least some data + firstUrlAndName = extractUrlAndName(policy[policyKey]) + } + } + } + } + + // Copy found language data by priority + when { + userLanguageUrlAndName != null -> { + localizedFlowDataLoginTermsLocalizedUrl = userLanguageUrlAndName!!.url + localizedFlowDataLoginTermsLocalizedName = userLanguageUrlAndName!!.name + } + defaultLanguageUrlAndName != null -> { + localizedFlowDataLoginTermsLocalizedUrl = defaultLanguageUrlAndName!!.url + localizedFlowDataLoginTermsLocalizedName = defaultLanguageUrlAndName!!.name + } + firstUrlAndName != null -> { + localizedFlowDataLoginTermsLocalizedUrl = firstUrlAndName!!.url + localizedFlowDataLoginTermsLocalizedName = firstUrlAndName!!.name + } + } + } + + result.add(LocalizedFlowDataLoginTerms( + policyName = localizedFlowDataLoginTermsPolicyName, + version = localizedFlowDataLoginTermsVersion, + localizedUrl = localizedFlowDataLoginTermsLocalizedUrl, + localizedName = localizedFlowDataLoginTermsLocalizedName + )) + } + } + + return result +} + +private fun extractUrlAndName(policyData: Any?): UrlAndName? { + if (policyData is Map<*, *>) { + val url = policyData["url"] as String? + val name = policyData["name"] as String? + + if (url != null && name != null) { + return UrlAndName(url, name) + } + } + return null +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt index 621253faa5c7d31692024c32602591777f8edd0b..0cda64499f126def2d5d006c0b1b1bca80661199 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.api.auth.registration +import org.matrix.android.sdk.api.util.JsonDict + /** * Set of methods to be able to create an account on a homeserver. * @@ -73,6 +75,13 @@ interface RegistrationWizard { */ suspend fun dummy(): RegistrationResult + /** + * Perform custom registration stage by sending a custom JsonDict. + * Current registration "session" param will be included into authParams by default. + * The authParams should contain at least one entry "type" with a String value. + */ + suspend fun registrationCustom(authParams: JsonDict): RegistrationResult + /** * Perform the "m.login.email.identity" or "m.login.msisdn" stage. * diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt index b5165b6687d403512b43e1eb36c109be3ff62d44..5b4896f95f2f170b1f2523a6cfda2de39727f03a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt @@ -23,5 +23,10 @@ sealed class GlobalError { data class InvalidToken(val softLogout: Boolean) : GlobalError() data class ConsentNotGivenError(val consentUri: String) : GlobalError() data class CertificateError(val fingerprint: Fingerprint) : GlobalError() + + /** + * The SDK requires the app (which should request the user) to perform an initial sync. + */ + data class InitialSyncRequest(val reason: InitialSyncRequestReason) : GlobalError() object ExpiredAccount : GlobalError() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt new file mode 100644 index 0000000000000000000000000000000000000000..ebe07823f470f3fbdca55586dcb49e2787742b06 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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.api.failure + +/** + * This enum provide the reason why the SDK request an initial sync to the application + */ +enum class InitialSyncRequestReason { + /** + * The list of ignored users has changed, and at least one user who was ignored is not ignored anymore + */ + IGNORED_USERS_LIST_CHANGE, +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt index be924e206367edac1242842571ab0c8652a76661..19502f0b46b873a1d658aad6986bbb53f9cce91c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt @@ -24,10 +24,8 @@ import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.auth.data.SessionParams import org.matrix.android.sdk.api.failure.GlobalError import org.matrix.android.sdk.api.federation.FederationService -import org.matrix.android.sdk.api.pushrules.PushRuleService import org.matrix.android.sdk.api.session.account.AccountService import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService -import org.matrix.android.sdk.api.session.cache.CacheService import org.matrix.android.sdk.api.session.call.CallSignalingService import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker import org.matrix.android.sdk.api.session.content.ContentUrlResolver @@ -47,6 +45,7 @@ import org.matrix.android.sdk.api.session.permalinks.PermalinkService import org.matrix.android.sdk.api.session.presence.PresenceService import org.matrix.android.sdk.api.session.profile.ProfileService import org.matrix.android.sdk.api.session.pushers.PushersService +import org.matrix.android.sdk.api.session.pushrules.PushRuleService import org.matrix.android.sdk.api.session.room.RoomDirectoryService import org.matrix.android.sdk.api.session.room.RoomService import org.matrix.android.sdk.api.session.search.SearchService @@ -68,26 +67,7 @@ import org.matrix.android.sdk.api.session.widgets.WidgetService * This interface defines interactions with a session. * An instance of a session will be provided by the SDK. */ -interface Session : - RoomService, - RoomDirectoryService, - GroupService, - UserService, - CacheService, - SignOutService, - FilterService, - TermsService, - EventService, - ProfileService, - PresenceService, - PushRuleService, - PushersService, - SyncStatusService, - HomeServerCapabilitiesService, - SecureStorageService, - AccountService, - ToDeviceService, - EventStreamService { +interface Session { val coroutineDispatchers: MatrixCoroutineDispatchers @@ -144,6 +124,11 @@ interface Session : */ fun stopSync() + /** + * Clear cache of the session + */ + suspend fun clearCache() + /** * This method allows to listen the sync state. * @return a [LiveData] of [SyncState]. @@ -206,6 +191,96 @@ interface Session : */ fun identityService(): IdentityService + /** + * Returns the HomeServerCapabilities service associated with the session + */ + fun homeServerCapabilitiesService(): HomeServerCapabilitiesService + + /** + * Returns the RoomService associated with the session + */ + fun roomService(): RoomService + + /** + * Returns the RoomDirectoryService associated with the session + */ + fun roomDirectoryService(): RoomDirectoryService + + /** + * Returns the GroupService associated with the session + */ + fun groupService(): GroupService + + /** + * Returns the UserService associated with the session + */ + fun userService(): UserService + + /** + * Returns the SignOutService associated with the session + */ + fun signOutService(): SignOutService + + /** + * Returns the FilterService associated with the session + */ + fun filterService(): FilterService + + /** + * Returns the PushRuleService associated with the session + */ + fun pushRuleService(): PushRuleService + + /** + * Returns the PushersService associated with the session + */ + fun pushersService(): PushersService + + /** + * Returns the EventService associated with the session + */ + fun eventService(): EventService + + /** + * Returns the TermsService associated with the session + */ + fun termsService(): TermsService + + /** + * Returns the SyncStatusService associated with the session + */ + fun syncStatusService(): SyncStatusService + + /** + * Returns the SecureStorageService associated with the session + */ + fun secureStorageService(): SecureStorageService + + /** + * Returns the ProfileService associated with the session + */ + fun profileService(): ProfileService + + /** + * Returns the PresenceService associated with the session + */ + fun presenceService(): PresenceService + + /** + * Returns the AccountService associated with the session + */ + fun accountService(): AccountService + + /** + * Returns the ToDeviceService associated with the session + */ + fun toDeviceService(): ToDeviceService + + /** + * Returns the EventStreamService associated with the session + */ + fun eventStreamService(): EventStreamService + /** * Returns the widget service associated with the session */ @@ -266,6 +341,11 @@ interface Session : */ fun accountDataService(): SessionAccountDataService + /** + * Returns the SharedSecretStorageService associated with the session + */ + fun sharedSecretStorageService(): SharedSecretStorageService + /** * Add a listener to the session. * @param listener the listener to add. @@ -298,12 +378,11 @@ interface Session : * Possible cases: * - The access token is not valid anymore, * - a M_CONSENT_NOT_GIVEN error has been received from the homeserver + * See [GlobalError] for all the possible cases */ fun onGlobalError(session: Session, globalError: GlobalError) = Unit } - val sharedSecretStorageService: SharedSecretStorageService - fun getUiaSsoFallbackUrl(authenticationSessionId: String): String /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt new file mode 100644 index 0000000000000000000000000000000000000000..aeb0e7e4ee73f5dee19e8e7cccb1ad16b1b4aa9a --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/SessionExtensions.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 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.api.session + +import org.matrix.android.sdk.api.session.room.Room +import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.session.user.model.User + +/** + * Get a room using the RoomService of a Session + */ +fun Session.getRoom(roomId: String): Room? = roomService().getRoom(roomId) + +/** + * Get a room summary using the RoomService of a Session + */ +fun Session.getRoomSummary(roomIdOrAlias: String): RoomSummary? = roomService().getRoomSummary(roomIdOrAlias) + +/** + * Get a user using the UserService of a Session + */ +fun Session.getUser(userId: String): User? = userService().getUser(userId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt index 74ca7304f7348386e65b4040b938a773852d1b5e..ad11ef9a5e465b2cfc04a92af2ecd43511404dbf 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt @@ -46,8 +46,9 @@ data class IncomingRequestCancellation( * Factory * * @param event the event + * @param currentTimeMillis the current time in milliseconds */ - fun fromEvent(event: Event): IncomingRequestCancellation? { + fun fromEvent(event: Event, currentTimeMillis: Long): IncomingRequestCancellation? { return event.getClearContent() .toModel<ShareRequestCancellation>() ?.let { @@ -55,7 +56,7 @@ data class IncomingRequestCancellation( userId = event.senderId, deviceId = it.requestingDeviceId, requestId = it.requestId, - localCreationTimestamp = event.ageLocalTs ?: System.currentTimeMillis() + localCreationTimestamp = event.ageLocalTs ?: currentTimeMillis ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt index 45b0926d8912cca217193efffc8d13f880d13fae..0b2c32284b05edd79316b5de883b5b5bb8e4d232 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt @@ -64,8 +64,9 @@ data class IncomingRoomKeyRequest( * Factory * * @param event the event + * @param currentTimeMillis the current time in milliseconds */ - fun fromEvent(event: Event): IncomingRoomKeyRequest? { + fun fromEvent(event: Event, currentTimeMillis: Long): IncomingRoomKeyRequest? { return event.getClearContent() .toModel<RoomKeyShareRequest>() ?.let { @@ -74,7 +75,7 @@ data class IncomingRoomKeyRequest( deviceId = it.requestingDeviceId, requestId = it.requestId, requestBody = it.body ?: RoomKeyRequestBody(), - localCreationTimestamp = event.ageLocalTs ?: System.currentTimeMillis() + localCreationTimestamp = event.ageLocalTs ?: currentTimeMillis ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt index 5afffef1aed4d2dafd4f6cb97c2ad2f931460468..80f70c83f3a6e7671bc53cc463b95b448ebe7d4e 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt @@ -64,8 +64,9 @@ data class IncomingSecretShareRequest( * Factory * * @param event the event + * @param currentTimeMillis the current time in milliseconds */ - fun fromEvent(event: Event): IncomingSecretShareRequest? { + fun fromEvent(event: Event, currentTimeMillis: Long): IncomingSecretShareRequest? { return event.getClearContent() .toModel<SecretShareRequest>() ?.let { @@ -74,7 +75,7 @@ data class IncomingSecretShareRequest( deviceId = it.requestingDeviceId, requestId = it.requestId, secretName = it.secretName, - localCreationTimestamp = event.ageLocalTs ?: System.currentTimeMillis() + localCreationTimestamp = event.ageLocalTs ?: currentTimeMillis ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt index b9d0c0ad2cec8fbaa65be1128496b74ab6859bb2..ec67e4b31d143adfdc048d6eea232d8be0376546 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationService.kt @@ -129,11 +129,10 @@ interface VerificationService { private const val TEN_MINUTES_IN_MILLIS = 10 * 60 * 1000 private const val FIVE_MINUTES_IN_MILLIS = 5 * 60 * 1000 - fun isValidRequest(age: Long?): Boolean { + fun isValidRequest(age: Long?, currentTimeMillis: Long): Boolean { if (age == null) return false - val now = System.currentTimeMillis() - val tooInThePast = now - TEN_MINUTES_IN_MILLIS - val tooInTheFuture = now + FIVE_MINUTES_IN_MILLIS + val tooInThePast = currentTimeMillis - TEN_MINUTES_IN_MILLIS + val tooInTheFuture = currentTimeMillis + FIVE_MINUTES_IN_MILLIS return age in tooInThePast..tooInTheFuture } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt index 72f8019ada3c45c1273324cfdb617c9e090e9ceb..e3ccbad2490b712587f7e15779c3524ad8ea30f3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt @@ -45,9 +45,9 @@ interface FileService { * Result will be a decrypted file, stored in the cache folder. url parameter will be used to create unique filename to avoid name collision. */ suspend fun downloadFile(fileName: String, - mimeType: String?, - url: String?, - elementToDecrypt: ElementToDecrypt?): File + mimeType: String?, + url: String?, + elementToDecrypt: ElementToDecrypt?): File suspend fun downloadFile(messageContent: MessageWithAttachmentContent): File = downloadFile( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt index 267436916ec33c27dd087fe9f6e6e9f83d5f7a26..759813939f432691cc4e9e389d362bf831759704 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt @@ -43,6 +43,7 @@ interface SyncStatusService { val rooms: Int, val toDevice: Int ) : IncrementalSyncStatus() + object IncrementalSyncError : IncrementalSyncStatus() object IncrementalSyncDone : IncrementalSyncStatus() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixLinkify.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixLinkify.kt index 3e27da0c41d9af9e45bd3b61869372dde1e780e0..c5d919407aecbf50ea6a03239c0a07266a520c7d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixLinkify.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/MatrixLinkify.kt @@ -55,7 +55,7 @@ object MatrixLinkify { MatrixPatterns.isRoomId(url) || MatrixPatterns.isGroupId(url) || MatrixPatterns.isEventId(url)) { - url = PermalinkService.MATRIX_TO_URL_BASE + url + url = PermalinkService.MATRIX_TO_URL_BASE + url } val span = MatrixPermalinkSpan(url, callback) spannable.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt index 85291cf0f6c59fbcce12f0f2a32ef97e072d4e7d..57aacc98b81a64509699d5707a393c04ca4c3e5a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt @@ -35,21 +35,21 @@ sealed class PermalinkData { /** * &room_name=Team2 - &room_avatar_url=mxc: - &inviter_name=bob + &room_avatar_url=mxc: + &inviter_name=bob */ @Parcelize data class RoomEmailInviteLink( - val roomId: String, - val email: String, - val signUrl: String, - val roomName: String?, - val roomAvatarUrl: String?, - val inviterName: String?, - val identityServer: String, - val token: String, - val privateKey: String, - val roomType: String? + val roomId: String, + val email: String, + val signUrl: String, + val roomName: String?, + val roomAvatarUrl: String?, + val inviterName: String?, + val identityServer: String, + val token: String, + val privateKey: String, + val roomType: String? ) : PermalinkData(), Parcelable data class UserLink(val userId: String) : PermalinkData() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt similarity index 97% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt index 30289531e747a94ec0a70d5234078b1982e417e0..7790942d8453bf4655f1dbad1521f36c9c0414a6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules -import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule import timber.log.Timber sealed class Action { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Condition.kt similarity index 93% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Condition.kt index 04cccf73192e9988c3a417d37e89fde0c08d4e6f..df5b056c2ebf3f2ae5f566d8e0a2b6db8ff50522 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Condition.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules import org.matrix.android.sdk.api.session.events.model.Event diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ConditionResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ConditionResolver.kt similarity index 96% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ConditionResolver.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ConditionResolver.kt index 0a7366e5d2210ca281c9b4ec4a450399bad15ab3..f8a930f987d1cd51ba5716f9ca5746e6ce159a63 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ConditionResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ConditionResolver.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules import org.matrix.android.sdk.api.session.events.model.Event diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ContainsDisplayNameCondition.kt similarity index 97% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ContainsDisplayNameCondition.kt index 7f430238738d7c6ac8b464915440768d0c13235a..69dd14ddc2c2468e6ea05150cf89c4dcf6a9a353 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/ContainsDisplayNameCondition.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/EventMatchCondition.kt similarity index 98% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/EventMatchCondition.kt index 65a13b4fec916b247206464408c2b169ce4cb990..8875807b8add337a6f439ca543f63f9d98ec887a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/EventMatchCondition.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.internal.di.MoshiProvider diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Kind.kt similarity index 96% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Kind.kt index 293a06af9f6343ccc5993ecbc64177f20c7256d7..463f3c2a73d0b4870b8a2e2ae718bcffe5ead215 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Kind.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules enum class Kind(val value: String) { EventMatch("event_match"), diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/PushEvents.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushEvents.kt similarity index 88% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/PushEvents.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushEvents.kt index 466e345cad5bd77969492df9854ccfca31b91f79..ee460d70762f9c0eb935357ee65be76c481423b0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/PushEvents.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushEvents.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules -import org.matrix.android.sdk.api.pushrules.rest.PushRule import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule data class PushEvents( val matchedEvents: List<Pair<Event, PushRule>>, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/PushRuleService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt similarity index 91% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/PushRuleService.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt index 76885d85454e5e0401273f438448a3e4785439ab..abbdbf81049660d2edd0411a0d1b2c5be7329983 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/PushRuleService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/PushRuleService.kt @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules import androidx.lifecycle.LiveData -import org.matrix.android.sdk.api.pushrules.rest.PushRule -import org.matrix.android.sdk.api.pushrules.rest.RuleSet import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.rest.RuleSet interface PushRuleService { /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RoomMemberCountCondition.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RoomMemberCountCondition.kt index 328e6dae118719b4ac601d095bd765e02e788af1..6973ff1372a30c0ec25620725e3597707d94f56e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RoomMemberCountCondition.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.internal.session.room.RoomGetter @@ -44,7 +44,7 @@ class RoomMemberCountCondition( // Parse the is field into prefix and number the first time val (prefix, count) = parseIsField() ?: return false - val numMembers = room.getNumberOfJoinedMembers() + val numMembers = room.membershipService().getNumberOfJoinedMembers() return when (prefix) { "<" -> numMembers < count diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RuleIds.kt similarity index 97% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RuleIds.kt index 5b14e97d5ea50ec6f8ebbd28f3b8045b3993a770..4f35fb79c3623c3fc81d78c8f96ecce45bffc41b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RuleIds.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules /** * Known rule ids diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleScope.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RuleScope.kt similarity index 92% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleScope.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RuleScope.kt index 7c1edc1aca03f096d9de26d763e3a631beca8ea9..307b9db042dd25110e990f42cb8071515d6f3da5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleScope.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RuleScope.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules object RuleScope { const val GLOBAL = "global" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleSetKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RuleSetKey.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleSetKey.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RuleSetKey.kt index 5b6f6713f8016e77238779a8acf20d8b904fbf64..7b8f4c9f958cf536bb3402fb69a6d8bd08b590aa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleSetKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/RuleSetKey.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules /** * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/SenderNotificationPermissionCondition.kt similarity index 97% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/SenderNotificationPermissionCondition.kt index 6675fb0ff5082b6b0d9169ecaf45937a3026ef73..82f5023c2f14a3bd630d10756e9577f03f31ff45 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/SenderNotificationPermissionCondition.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushCondition.kt similarity index 84% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushCondition.kt index b31a1e6343929fef3481325a0188a5179026450a..1fc8329535460aa9176e6e368b7f4718be8e52c6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushCondition.kt @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules.rest +package org.matrix.android.sdk.api.session.pushrules.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.pushrules.Condition -import org.matrix.android.sdk.api.pushrules.ContainsDisplayNameCondition -import org.matrix.android.sdk.api.pushrules.EventMatchCondition -import org.matrix.android.sdk.api.pushrules.Kind -import org.matrix.android.sdk.api.pushrules.RoomMemberCountCondition -import org.matrix.android.sdk.api.pushrules.RuleIds -import org.matrix.android.sdk.api.pushrules.SenderNotificationPermissionCondition +import org.matrix.android.sdk.api.session.pushrules.Condition +import org.matrix.android.sdk.api.session.pushrules.ContainsDisplayNameCondition +import org.matrix.android.sdk.api.session.pushrules.EventMatchCondition +import org.matrix.android.sdk.api.session.pushrules.Kind +import org.matrix.android.sdk.api.session.pushrules.RoomMemberCountCondition +import org.matrix.android.sdk.api.session.pushrules.RuleIds +import org.matrix.android.sdk.api.session.pushrules.SenderNotificationPermissionCondition import timber.log.Timber /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt index 31d7770a9f4a62193825f39e81f97dc9f85ac6a7..270ffb29408ec9a2699fdb8dc2963b1cf443de0d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules.rest +package org.matrix.android.sdk.api.session.pushrules.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.api.pushrules.Action -import org.matrix.android.sdk.api.pushrules.getActions -import org.matrix.android.sdk.api.pushrules.toJson +import org.matrix.android.sdk.api.session.pushrules.Action +import org.matrix.android.sdk.api.session.pushrules.getActions +import org.matrix.android.sdk.api.session.pushrules.toJson /** * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/RuleSet.kt similarity index 93% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/RuleSet.kt index 46f5148714db5f447d46cbd5b40636488c6df428..5bf42b8252a63f4dd258dac3ace31250f79e073e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/RuleSet.kt @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules.rest +package org.matrix.android.sdk.api.session.pushrules.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.pushrules.RuleIds -import org.matrix.android.sdk.api.pushrules.RuleSetKey +import org.matrix.android.sdk.api.session.pushrules.RuleIds +import org.matrix.android.sdk.api.session.pushrules.RuleSetKey /** * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt index be65b883b36238509027a6398e61652138232e7f..1f990f4c0a51cdf083a214e3b72329f9f6e0794e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt @@ -38,33 +38,13 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineService import org.matrix.android.sdk.api.session.room.typing.TypingService import org.matrix.android.sdk.api.session.room.uploads.UploadsService import org.matrix.android.sdk.api.session.room.version.RoomVersionService -import org.matrix.android.sdk.api.session.search.SearchResult import org.matrix.android.sdk.api.session.space.Space import org.matrix.android.sdk.api.util.Optional /** * This interface defines methods to interact within a room. */ -interface Room : - TimelineService, - ThreadsService, - ThreadsLocalService, - SendService, - DraftService, - ReadService, - TypingService, - AliasService, - TagsService, - MembershipService, - StateService, - UploadsService, - ReportingService, - RoomCallService, - RelationService, - RoomCryptoService, - RoomPushRuleService, - RoomAccountDataService, - RoomVersionService { +interface Room { val coroutineDispatchers: MatrixCoroutineDispatchers @@ -85,27 +65,102 @@ interface Room : fun roomSummary(): RoomSummary? /** - * Generic function to search a term in a room. - * Ref: https://matrix.org/docs/spec/client_server/latest#module-search - * @param searchTerm the term to search - * @param nextBatch the token that retrieved from the previous response. Should be provided to get the next batch of results - * @param orderByRecent if true, the most recent message events will return in the first places of the list - * @param limit the maximum number of events to return. - * @param beforeLimit how many events before the result are returned. - * @param afterLimit how many events after the result are returned. - * @param includeProfile requests that the server returns the historic profile information for the users that sent the events that were returned. - * @return The search result + * Use this room as a Space, if the type is correct. */ - suspend fun search(searchTerm: String, - nextBatch: String?, - orderByRecent: Boolean, - limit: Int, - beforeLimit: Int, - afterLimit: Int, - includeProfile: Boolean): SearchResult + fun asSpace(): Space? /** - * Use this room as a Space, if the type is correct. + * Get the TimelineService associated to this Room */ - fun asSpace(): Space? + fun timelineService(): TimelineService + + /** + * Get the ThreadsService associated to this Room + */ + fun threadsService(): ThreadsService + + /** + * Get the ThreadsLocalService associated to this Room + */ + fun threadsLocalService(): ThreadsLocalService + + /** + * Get the SendService associated to this Room + */ + fun sendService(): SendService + + /** + * Get the DraftService associated to this Room + */ + fun draftService(): DraftService + + /** + * Get the ReadService associated to this Room + */ + fun readService(): ReadService + + /** + * Get the TypingService associated to this Room + */ + fun typingService(): TypingService + + /** + * Get the AliasService associated to this Room + */ + fun aliasService(): AliasService + + /** + * Get the TagsService associated to this Room + */ + fun tagsService(): TagsService + + /** + * Get the MembershipService associated to this Room + */ + fun membershipService(): MembershipService + + /** + * Get the StateService associated to this Room + */ + fun stateService(): StateService + + /** + * Get the UploadsService associated to this Room + */ + fun uploadsService(): UploadsService + + /** + * Get the ReportingService associated to this Room + */ + fun reportingService(): ReportingService + + /** + * Get the RoomCallService associated to this Room + */ + fun roomCallService(): RoomCallService + + /** + * Get the RelationService associated to this Room + */ + fun relationService(): RelationService + + /** + * Get the RoomCryptoService associated to this Room + */ + fun roomCryptoService(): RoomCryptoService + + /** + * Get the RoomPushRuleService associated to this Room + */ + fun roomPushRuleService(): RoomPushRuleService + + /** + * Get the RoomAccountDataService associated to this Room + */ + fun roomAccountDataService(): RoomAccountDataService + + /** + * Get the RoomVersionService associated to this Room + */ + fun roomVersionService(): RoomVersionService } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt new file mode 100644 index 0000000000000000000000000000000000000000..ece9cfbfacf59a77f9f9a7cfc57fb48041f5a6bf --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomExtensions.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 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.api.session.room + +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.timeline.TimelineEvent + +/** + * Get a TimelineEvent using the TimelineService of a Room + */ +fun Room.getTimelineEvent(eventId: String): TimelineEvent? = + timelineService().getTimelineEvent(eventId) + +/** + * Get a StateEvent using the StateService of a Room + */ +fun Room.getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event? = + stateService().getStateEvent(eventType, stateKey) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/EventAnnotationsSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/EventAnnotationsSummary.kt index 0238eb6c8dee4dbdd93c46efba0df588986fe517..0aded203395d5fcfaa30839734953e5bf01f1c7a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/EventAnnotationsSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/EventAnnotationsSummary.kt @@ -15,10 +15,12 @@ */ package org.matrix.android.sdk.api.session.room.model +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary + data class EventAnnotationsSummary( - val eventId: String, val reactionsSummary: List<ReactionAggregatedSummary> = emptyList(), val editSummary: EditAggregatedSummary? = null, val pollResponseSummary: PollResponseAggregatedSummary? = null, - val referencesAggregatedSummary: ReferencesAggregatedSummary? = null + val referencesAggregatedSummary: ReferencesAggregatedSummary? = null, + val liveLocationShareAggregatedSummary: LiveLocationShareAggregatedSummary? = null, ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedSummary.kt index 31ac09efb851bba6ca6dbc429dbbf8deb0b009d8..49ba2d5ab6a1015d85eef6cc5bd3775bc5a6ed21 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedSummary.kt @@ -22,7 +22,6 @@ import org.matrix.android.sdk.api.session.events.model.Content * of all events that are referencing the 'eventId' event via the RelationType.REFERENCE */ data class ReferencesAggregatedSummary( - val eventId: String, val content: Content?, val sourceEvents: List<String>, val localEchos: List<String> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt index 871b299f93bcfa7142b0d50ecac25e18932d2ef8..5237b10d52b3cbd8d9edcdb85309029ad7caa8e9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt @@ -36,10 +36,10 @@ data class RoomJoinRulesContent( @Json(name = "allow") val allowList: List<RoomJoinRulesAllowEntry>? = null ) { val joinRules: RoomJoinRules? = when (_joinRules) { - "public" -> RoomJoinRules.PUBLIC - "invite" -> RoomJoinRules.INVITE - "knock" -> RoomJoinRules.KNOCK - "private" -> RoomJoinRules.PRIVATE + "public" -> RoomJoinRules.PUBLIC + "invite" -> RoomJoinRules.INVITE + "knock" -> RoomJoinRules.KNOCK + "private" -> RoomJoinRules.PRIVATE "restricted" -> RoomJoinRules.RESTRICTED else -> { Timber.w("Invalid value for RoomJoinRules: `$_joinRules`") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallAnswerContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallAnswerContent.kt index 6b4d78283264799cb76a8f1229052e6245f24660..67ef85787ecfb87348aaa0d4afab3eeca9ab0c18 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallAnswerContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallAnswerContent.kt @@ -44,7 +44,7 @@ data class CallAnswerContent( * Capability advertisement. */ @Json(name = "capabilities") val capabilities: CallCapabilities? = null -) : CallSignalingContent { +) : CallSignalingContent { @JsonClass(generateAdapter = true) data class Answer( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallInviteContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallInviteContent.kt index d70e63d1226f421f72849508fd28c091534f30fb..24c8152f3cca195faa00c3ada52b74688ea5665f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallInviteContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallInviteContent.kt @@ -55,7 +55,7 @@ data class CallInviteContent( */ @Json(name = "capabilities") val capabilities: CallCapabilities? = null -) : CallSignalingContent { +) : CallSignalingContent { @JsonClass(generateAdapter = true) data class Offer( /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallNegotiateContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallNegotiateContent.kt index bbbfbe68ab8c8c061d891f2fe50deb11bdf3438c..5c6c6cda01a2c1db3b30dc88e60e6d436c52d8a2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallNegotiateContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallNegotiateContent.kt @@ -47,7 +47,7 @@ data class CallNegotiateContent( */ @Json(name = "version") override val version: String? - ) : CallSignalingContent { +) : CallSignalingContent { @JsonClass(generateAdapter = true) data class Description( /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallReplacesContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallReplacesContent.kt index 7947b7d0bd1b545738ce28d4f3bf69d8ae2cc494..e480e013ea9ced4c49dffe7029a3a6a0dddbc719 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallReplacesContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/call/CallReplacesContent.kt @@ -61,7 +61,7 @@ data class CallReplacesContent( * Required. The version of the VoIP specification this messages adheres to. */ @Json(name = "version") override val version: String? -) : CallSignalingContent { +) : CallSignalingContent { @JsonClass(generateAdapter = true) data class TargetUser( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt new file mode 100644 index 0000000000000000000000000000000000000000..0b28d62f56b8d0ae02856d248a5272c6db131732 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationShareAggregatedSummary.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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.api.session.room.model.livelocation + +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent + +/** + * Aggregation info concerning a live location share. + */ +data class LiveLocationShareAggregatedSummary( + val isActive: Boolean?, + val endOfLiveTimestampMillis: Long?, + val lastLocationDataContent: MessageBeaconLocationDataContent?, +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt index fa18bfd21f79485bc05a3baaf397a444b6b7752a..132b72902f5e9de2c397fc6ded5c29ce468ad25f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt @@ -52,5 +52,5 @@ data class FileInfo( * Get the url of the encrypted thumbnail or of the thumbnail */ fun FileInfo.getThumbnailUrl(): String? { - return thumbnailFile?.url ?: thumbnailUrl + return thumbnailFile?.url ?: thumbnailUrl } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt index 0099208320ee6f28a54c45bf3a3c64d3b173d573..bd99ea690019b9ba428f5bf0d96376226e553eaa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt @@ -62,5 +62,5 @@ data class ImageInfo( * Get the url of the encrypted thumbnail or of the thumbnail */ fun ImageInfo.getThumbnailUrl(): String? { - return thumbnailFile?.url ?: thumbnailUrl + return thumbnailFile?.url ?: thumbnailUrl } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationBeaconContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconInfoContent.kt similarity index 57% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationBeaconContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconInfoContent.kt index 106e76eafd08889017852326406aedd4738ab502..f75704a89158b704dca114a22b13439c1ee1b8b0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationBeaconContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconInfoContent.kt @@ -14,60 +14,59 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.session.room.model.livelocation +package org.matrix.android.sdk.api.session.room.model.message import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.session.events.model.Content -import org.matrix.android.sdk.api.session.room.model.message.LocationAsset -import org.matrix.android.sdk.api.session.room.model.message.LocationAssetType -import org.matrix.android.sdk.api.session.room.model.message.MessageContent -import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent -import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent +/** + * Content of the state event of type + * [EventType.STATE_ROOM_BEACON_INFO][org.matrix.android.sdk.api.session.events.model.EventType.STATE_ROOM_BEACON_INFO] + * + * It contains general info related to a live location share. + * Locations are sent in a different message related to the state event. + * See [MessageBeaconLocationDataContent][org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent] + */ @JsonClass(generateAdapter = true) -data class LiveLocationBeaconContent( +data class MessageBeaconInfoContent( /** * Local message type, not from server */ @Transient - override val msgType: String = MessageType.MSGTYPE_LIVE_LOCATION_STATE, + override val msgType: String = MessageType.MSGTYPE_BEACON_INFO, @Json(name = "body") override val body: String = "", @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null, /** - * Indicates user's intent to share ephemeral location. + * Optional description of the beacon. */ - @Json(name = "org.matrix.msc3672.beacon_info") val unstableBeaconInfo: BeaconInfo? = null, - @Json(name = "m.beacon_info") val beaconInfo: BeaconInfo? = null, + @Json(name = "description") val description: String? = null, /** - * Beacon creation timestamp. + * Beacon should be considered as inactive after this timeout as milliseconds. */ - @Json(name = "org.matrix.msc3488.ts") val unstableTimestampAsMilliseconds: Long? = null, - @Json(name = "m.ts") val timestampAsMilliseconds: Long? = null, + @Json(name = "timeout") val timeout: Long? = null, /** - * Live location asset type. + * Should be set true to start sharing beacon. */ - @Json(name = "org.matrix.msc3488.asset") val unstableLocationAsset: LocationAsset = LocationAsset(LocationAssetType.SELF), - @Json(name = "m.asset") val locationAsset: LocationAsset? = null, + @Json(name = "live") val isLive: Boolean? = null, /** - * Client side tracking of the last location + * Beacon creation timestamp. */ - var lastLocationContent: MessageLiveLocationContent? = null, - + @Json(name = "org.matrix.msc3488.ts") val unstableTimestampMillis: Long? = null, + @Json(name = "m.ts") val timestampMillis: Long? = null, /** - * Client side tracking of whether the beacon has timed out. + * Live location asset type. */ - var hasTimedOut: Boolean = false + @Json(name = "org.matrix.msc3488.asset") val unstableLocationAsset: LocationAsset = LocationAsset(LocationAssetType.SELF), + @Json(name = "m.asset") val locationAsset: LocationAsset? = null, ) : MessageContent { - fun getBestBeaconInfo() = beaconInfo ?: unstableBeaconInfo - - fun getBestTimestampAsMilliseconds() = timestampAsMilliseconds ?: unstableTimestampAsMilliseconds + fun getBestTimestampMillis() = timestampMillis ?: unstableTimestampMillis fun getBestLocationAsset() = locationAsset ?: unstableLocationAsset } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLiveLocationContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt similarity index 72% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLiveLocationContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt index 548dc8536944d16e4d84f3187104840b704d37d8..4a4ef46bc84b583d8050a0db242c8983469e3216 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLiveLocationContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt @@ -21,13 +21,21 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent +/** + * Content of the state event of type + * [EventType.BEACON_LOCATION_DATA][org.matrix.android.sdk.api.session.events.model.EventType.BEACON_LOCATION_DATA] + * + * It contains location data related to a live location share. + * It is related to the state event that originally started the live. + * See [MessageBeaconInfoContent][org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent] + */ @JsonClass(generateAdapter = true) -data class MessageLiveLocationContent( +data class MessageBeaconLocationDataContent( /** * Local message type, not from server */ @Transient - override val msgType: String = MessageType.MSGTYPE_LIVE_LOCATION, + override val msgType: String = MessageType.MSGTYPE_BEACON_LOCATION_DATA, @Json(name = "body") override val body: String = "", @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @@ -42,11 +50,11 @@ data class MessageLiveLocationContent( /** * Exact time that the data in the event refers to (milliseconds since the UNIX epoch) */ - @Json(name = "org.matrix.msc3488.ts") val unstableTimestampAsMilliseconds: Long? = null, - @Json(name = "m.ts") val timestampAsMilliseconds: Long? = null + @Json(name = "org.matrix.msc3488.ts") val unstableTimestampMillis: Long? = null, + @Json(name = "m.ts") val timestampMillis: Long? = null ) : MessageContent { fun getBestLocationInfo() = locationInfo ?: unstableLocationInfo - fun getBestTimestampAsMilliseconds() = timestampAsMilliseconds ?: unstableTimestampAsMilliseconds + fun getBestTimestampMillis() = timestampMillis ?: unstableTimestampMillis } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt index 2052133b068cf360d7da16ae60ae7fb4f758edce..19cb20430d2968b3d3cad8f7f28f95c3be00f113 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt @@ -49,8 +49,8 @@ data class MessageLocationContent( /** * Exact time that the data in the event refers to (milliseconds since the UNIX epoch) */ - @Json(name = "org.matrix.msc3488.ts") val unstableTs: Long? = null, - @Json(name = "m.ts") val ts: Long? = null, + @Json(name = "org.matrix.msc3488.ts") val unstableTimestampMillis: Long? = null, + @Json(name = "m.ts") val timestampMillis: Long? = null, @Json(name = "org.matrix.msc1767.text") val unstableText: String? = null, @Json(name = "m.text") val text: String? = null, /** @@ -66,7 +66,7 @@ data class MessageLocationContent( fun getBestLocationInfo() = locationInfo ?: unstableLocationInfo - fun getBestTs() = ts ?: unstableTs + fun getBestTimestampMillis() = timestampMillis ?: unstableTimestampMillis fun getBestText() = text ?: unstableText diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageType.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageType.kt index 106bf2e03085fa4847ee829df59caf3a293616bb..b12d9ed6c825145c7d029e816be8ba4bdc8ce999 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageType.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageType.kt @@ -41,6 +41,6 @@ object MessageType { const val MSGTYPE_SNOWFALL = "io.element.effect.snowfall" // Fake message types for live location events to be able to inherit them from MessageContent - const val MSGTYPE_LIVE_LOCATION_STATE = "org.matrix.android.sdk.livelocation.state" - const val MSGTYPE_LIVE_LOCATION = "org.matrix.android.sdk.livelocation" + const val MSGTYPE_BEACON_INFO = "org.matrix.android.sdk.beacon.info" + const val MSGTYPE_BEACON_LOCATION_DATA = "org.matrix.android.sdk.beacon.location.data" } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationRequestContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationRequestContent.kt index b2b3cdac9090b231389aa2799e04e75b81cf5c2b..a0699831f72b3152fa6209f41a9c0c8254cb6e44 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationRequestContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVerificationRequestContent.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoReque @JsonClass(generateAdapter = true) data class MessageVerificationRequestContent( - @Json(name = MessageContent.MSG_TYPE_JSON_KEY)override val msgType: String = MessageType.MSGTYPE_VERIFICATION_REQUEST, + @Json(name = MessageContent.MSG_TYPE_JSON_KEY) override val msgType: String = MessageType.MSGTYPE_VERIFICATION_REQUEST, @Json(name = "body") override val body: String, @Json(name = "from_device") override val fromDevice: String?, @Json(name = "methods") override val methods: List<String>, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt index 9266a0fb0f368e18a2ed87b67c681e8b2250ada4..9b657971b9258cb50413a54152ccb4493b77addf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt @@ -27,7 +27,7 @@ data class MessageVideoContent( /** * Required. Must be 'm.video'. */ - @Json(name = MessageContent.MSG_TYPE_JSON_KEY)override val msgType: String, + @Json(name = MessageContent.MSG_TYPE_JSON_KEY) override val msgType: String, /** * Required. A description of the video e.g. 'Gangnam style', or some kind of content description for accessibility e.g. 'video attachment'. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt index 28f3a47d114ef7986ab5207161624ffddfc72d6b..b02b4d96adc7696ffe8ca16d54f02e4a375ad636 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt @@ -67,5 +67,5 @@ data class VideoInfo( * Get the url of the encrypted thumbnail or of the thumbnail */ fun VideoInfo.getThumbnailUrl(): String? { - return thumbnailFile?.url ?: thumbnailUrl + return thumbnailFile?.url ?: thumbnailUrl } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt index f645f3ebf9cb94d021091995def4beaa9b8cb412..98171795e2cb30307f80af2d7d63aaaa730217f7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt @@ -84,8 +84,9 @@ interface StateService { * @param eventType The type of event to send. * @param stateKey The state_key for the state to send. Can be an empty string. * @param body The content object of the event; the fields in this object will vary depending on the type of event + * @return the id of the created state event */ - suspend fun sendStateEvent(eventType: String, stateKey: String, body: JsonDict) + suspend fun sendStateEvent(eventType: String, stateKey: String, body: JsonDict): String /** * Get a state event of the room diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt index a2ae8bfeb52e5b88068efff6e215a44a0b50a189..adbc8ab12a02ea8c1aa8196dde983a20d84abf11 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt @@ -29,7 +29,7 @@ import org.matrix.android.sdk.api.session.events.model.isSticker import org.matrix.android.sdk.api.session.events.model.toModel 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.livelocation.LiveLocationBeaconContent +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent @@ -139,7 +139,7 @@ fun TimelineEvent.getLastMessageContent(): MessageContent? { return when (root.getClearType()) { EventType.STICKER -> root.getClearContent().toModel<MessageStickerContent>() in EventType.POLL_START -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel<MessagePollContent>() - in EventType.STATE_ROOM_BEACON_INFO -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel<LiveLocationBeaconContent>() + in EventType.STATE_ROOM_BEACON_INFO -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel<MessageBeaconInfoContent>() else -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt index 4415c8e4b307dc31e2d08e262d788b361ef5e99b..a35a291d9b2342f385447efb167da54c221d3080 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt @@ -16,6 +16,7 @@ package org.matrix.android.sdk.api.session.room.timeline +// TODO Move to internal, strange? data class TimelineEventFilters( /** * A flag to filter edit events diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt index 6548453c8a126da8f203c82957ed46083781f59d..b45f3ecb71f5ff6ff90de643c6f9bdf93e1ad7ae 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt @@ -31,7 +31,8 @@ data class TimelineSettings( /** * The root thread eventId if this is a thread timeline, or null if this is NOT a thread timeline */ - val rootThreadEventId: String? = null) { + val rootThreadEventId: String? = null, +) { /** * Returns true if this is a thread timeline or false otherwise diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageError.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageError.kt index a91b97b86cd74531c6be22535b93de260e264f46..038533c19e814c562fda444f087091d31b79fe7c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageError.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageError.kt @@ -23,7 +23,7 @@ sealed class SharedSecretStorageError(message: String?) : Throwable(message) { data class UnsupportedAlgorithm(val algorithm: String) : SharedSecretStorageError("Unknown algorithm $algorithm") data class SecretNotEncrypted(val secretName: String) : SharedSecretStorageError("Missing content for secret $secretName") data class SecretNotEncryptedWithKey(val secretName: String, val keyId: String) : - SharedSecretStorageError("Missing content for secret $secretName with key $keyId") + SharedSecretStorageError("Missing content for secret $secretName with key $keyId") object BadKeyFormat : SharedSecretStorageError("Bad Key Format") object ParsingError : SharedSecretStorageError("parsing Error") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt index 78267640675bea67c87b30a07aa55d283503bbfe..afd26f7be54e10d545732d2131dc54a3d267556d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt @@ -68,7 +68,7 @@ interface SpaceService { suggestedOnly: Boolean? = null, limit: Int? = null, from: String? = null, - // when paginating, pass back the m.space.child state events + // when paginating, pass back the m.space.child state events knownStateList: List<Event>? = null): SpaceHierarchyData /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/UiaResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/UiaResult.kt new file mode 100644 index 0000000000000000000000000000000000000000..ee4a180dea394def649e236834340191ba7e0fac --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/UiaResult.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2022 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.api.session.uia + +enum class UiaResult { + SUCCESS, + FAILURE, + CANCELLED +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/exceptions/UiaCancelledException.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/exceptions/UiaCancelledException.kt new file mode 100644 index 0000000000000000000000000000000000000000..d5f9d72efe5674fb8177ebd727cfe4f4aad339f4 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/exceptions/UiaCancelledException.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2022 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.api.session.uia.exceptions + +class UiaCancelledException(message: String? = null) : Exception(message) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt index 554e21ce55981a76522302f4bde66b3562b37619..ebad859b05178c9b0b8ac79753045606448e9988 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt @@ -26,6 +26,7 @@ import org.matrix.android.sdk.internal.auth.data.WebClientConfig import org.matrix.android.sdk.internal.auth.login.ResetPasswordMailConfirmed import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationParams import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationResponse +import org.matrix.android.sdk.internal.auth.registration.RegistrationCustomParams import org.matrix.android.sdk.internal.auth.registration.RegistrationParams import org.matrix.android.sdk.internal.auth.registration.SuccessResult import org.matrix.android.sdk.internal.auth.registration.ValidationCodeBody @@ -68,6 +69,14 @@ internal interface AuthAPI { @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "register") suspend fun register(@Body registrationParams: RegistrationParams): Credentials + /** + * Register to the homeserver, or get error 401 with a RegistrationFlowResponse object if registration is incomplete + * method to perform other custom stages + * Ref: https://matrix.org/docs/spec/client_server/latest#account-registration-and-management + */ + @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "register") + suspend fun registerCustom(@Body registrationCustomParams: RegistrationCustomParams): Credentials + /** * Checks to see if a username is available, and valid, for the server. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt index 4a156e74cd994743205e42240a5d6f887c065b53..590b333e9008ec64d799db074f19f660bcfd6ec1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.auth.registration import kotlinx.coroutines.delay +import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.auth.registration.RegisterThreePid import org.matrix.android.sdk.api.auth.registration.RegistrationAvailability @@ -25,6 +26,7 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationWizard import org.matrix.android.sdk.api.auth.registration.toFlowResult import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.Failure.RegistrationFlowError +import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.auth.AuthAPI import org.matrix.android.sdk.internal.auth.PendingSessionStore import org.matrix.android.sdk.internal.auth.SessionCreator @@ -45,6 +47,7 @@ internal class DefaultRegistrationWizard( private val registerAvailableTask: RegisterAvailableTask = DefaultRegisterAvailableTask(authAPI) private val registerAddThreePidTask: RegisterAddThreePidTask = DefaultRegisterAddThreePidTask(authAPI) private val validateCodeTask: ValidateCodeTask = DefaultValidateCodeTask(authAPI) + private val registerCustomTask: RegisterCustomTask = DefaultRegisterCustomTask(authAPI) override val currentThreePid: String? get() { @@ -187,22 +190,51 @@ internal class DefaultRegistrationWizard( return performRegistrationRequest(params) } - private suspend fun performRegistrationRequest(registrationParams: RegistrationParams, - delayMillis: Long = 0): RegistrationResult { + override suspend fun registrationCustom( + authParams: JsonDict + ): RegistrationResult { + val safeSession = pendingSessionData.currentSession + ?: throw IllegalStateException("developer error, call createAccount() method first") + + val mutableParams = authParams.toMutableMap() + mutableParams["session"] = safeSession + + val params = RegistrationCustomParams(auth = mutableParams) + return performRegistrationOtherRequest(params) + } + + private suspend fun performRegistrationRequest( + registrationParams: RegistrationParams, + delayMillis: Long = 0 + ): RegistrationResult { delay(delayMillis) + return register { registerTask.execute(RegisterTask.Params(registrationParams)) } + } + + private suspend fun performRegistrationOtherRequest( + registrationCustomParams: RegistrationCustomParams + ): RegistrationResult { + return register { registerCustomTask.execute(RegisterCustomTask.Params(registrationCustomParams)) } + } + + private suspend fun register( + execute: suspend () -> Credentials + ): RegistrationResult { val credentials = try { - registerTask.execute(RegisterTask.Params(registrationParams)) + execute.invoke() } catch (exception: Throwable) { if (exception is RegistrationFlowError) { - pendingSessionData = pendingSessionData.copy(currentSession = exception.registrationFlowResponse.session) - .also { pendingSessionStore.savePendingSessionData(it) } + pendingSessionData = + pendingSessionData.copy(currentSession = exception.registrationFlowResponse.session) + .also { pendingSessionStore.savePendingSessionData(it) } return RegistrationResult.FlowResponse(exception.registrationFlowResponse.toFlowResult()) } else { throw exception } } - val session = sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig) + val session = + sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig) return RegistrationResult.Success(session) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterCustomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterCustomTask.kt new file mode 100644 index 0000000000000000000000000000000000000000..60af708c38e86ba4646c9261b73e0078346fcc1a --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterCustomTask.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2021 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.internal.auth.registration + +import org.matrix.android.sdk.api.auth.data.Credentials +import org.matrix.android.sdk.api.failure.Failure +import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse +import org.matrix.android.sdk.internal.auth.AuthAPI +import org.matrix.android.sdk.internal.network.executeRequest +import org.matrix.android.sdk.internal.task.Task + +internal interface RegisterCustomTask : Task<RegisterCustomTask.Params, Credentials> { + data class Params( + val registrationCustomParams: RegistrationCustomParams + ) +} + +internal class DefaultRegisterCustomTask( + private val authAPI: AuthAPI +) : RegisterCustomTask { + + override suspend fun execute(params: RegisterCustomTask.Params): Credentials { + try { + return executeRequest(null) { + authAPI.registerCustom(params.registrationCustomParams) + } + } catch (throwable: Throwable) { + throw throwable.toRegistrationFlowResponse() + ?.let { Failure.RegistrationFlowError(it) } + ?: throwable + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/BeaconInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegistrationCustomParams.kt similarity index 56% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/BeaconInfo.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegistrationCustomParams.kt index 873edc0f1fd3ac2976021ea87351039792b8f3e1..45adac6c2691bd9d8c2f47abe681f6e315dc392c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/BeaconInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegistrationCustomParams.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Matrix.org Foundation C.I.C. + * Copyright 2021 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. @@ -14,20 +14,18 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.session.room.model.livelocation +package org.matrix.android.sdk.internal.auth.registration import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.util.JsonDict +/** + * Class to pass parameters to the custom registration types for /register. + */ @JsonClass(generateAdapter = true) -data class BeaconInfo( - @Json(name = "description") val description: String? = null, - /** - * Beacon should be considered as inactive after this timeout as milliseconds. - */ - @Json(name = "timeout") val timeout: Long? = null, - /** - * Should be set true to start sharing beacon. - */ - @Json(name = "live") val isLive: Boolean? = null +internal data class RegistrationCustomParams( + // authentication parameters + @Json(name = "auth") + val auth: JsonDict? = null, ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt index da0866a5fd56b3e8e7ec58f907c930d78ce74bb4..7dafacb3c06ad3b8202f0681dc8cf8a323eb3157 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/UIAExt.kt @@ -20,6 +20,8 @@ import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse +import org.matrix.android.sdk.api.session.uia.UiaResult +import org.matrix.android.sdk.api.session.uia.exceptions.UiaCancelledException import timber.log.Timber import kotlin.coroutines.suspendCoroutine @@ -30,14 +32,15 @@ import kotlin.coroutines.suspendCoroutine * @param interceptor see doc in [UserInteractiveAuthInterceptor] * @param retryBlock called at the end of the process, in this block generally retry executing the task, with * provided authUpdate - * @return true if UIA is handled without error + * @return UiaResult if UIA handled, failed or cancelled + * */ internal suspend fun handleUIA(failure: Throwable, interceptor: UserInteractiveAuthInterceptor, - retryBlock: suspend (UIABaseAuth) -> Unit): Boolean { + retryBlock: suspend (UIABaseAuth) -> Unit): UiaResult { Timber.d("## UIA: check error ${failure.message}") val flowResponse = failure.toRegistrationFlowResponse() - ?: return false.also { + ?: return UiaResult.FAILURE.also { Timber.d("## UIA: not a UIA error") } @@ -50,14 +53,19 @@ internal suspend fun handleUIA(failure: Throwable, interceptor.performStage(flowResponse, (failure as? Failure.ServerError)?.error?.code, continuation) } } catch (failure2: Throwable) { - Timber.w(failure2, "## UIA: failed to participate") - return false + return if (failure2 is UiaCancelledException) { + Timber.w(failure2, "## UIA: cancelled") + UiaResult.CANCELLED + } else { + Timber.w(failure2, "## UIA: failed to participate") + UiaResult.FAILURE + } } Timber.d("## UIA: updated auth") return try { retryBlock(authUpdate) - true + UiaResult.SUCCESS } catch (failure3: Throwable) { handleUIA(failure3, interceptor, retryBlock) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt index 98950374eddb2e12db908c4b9090570a881d50be..aaf23d17b366723fb91587dcd88d8be1dbe6a938 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt @@ -32,12 +32,13 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId import org.matrix.android.sdk.internal.session.SessionComponent +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker import org.matrix.android.sdk.internal.worker.SessionWorkerParams import javax.inject.Inject internal class CancelGossipRequestWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<CancelGossipRequestWorker.Params>(context, params, sessionManager, Params::class.java) { + SessionSafeCoroutineWorker<CancelGossipRequestWorker.Params>(context, params, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( @@ -65,6 +66,7 @@ internal class CancelGossipRequestWorker(context: Context, params: WorkerParamet @Inject lateinit var sendToDeviceTask: SendToDeviceTask @Inject lateinit var cryptoStore: IMXCryptoStore @Inject lateinit var credentials: Credentials + @Inject lateinit var clock: Clock override fun injectWith(injector: SessionComponent) { injector.inject(this) @@ -85,7 +87,7 @@ internal class CancelGossipRequestWorker(context: Context, params: WorkerParamet content = toDeviceContent.toContent(), senderId = credentials.userId ).also { - it.ageLocalTs = System.currentTimeMillis() + it.ageLocalTs = clock.epochMillis() }) params.recipients.forEach { userToDeviceMap -> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt index 2a58d731e5310215631eb359362ede7b17426f25..73dfc468d97a2ba35189dfdb0ac7eaae954c1d96 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt @@ -48,7 +48,7 @@ internal class CryptoSessionInfoProvider @Inject constructor( /** * @param allActive if true return joined as well as invited, if false, only joined */ - fun getRoomUserIds(roomId: String, allActive: Boolean): List<String> { + fun getRoomUserIds(roomId: String, allActive: Boolean): List<String> { var userIds: List<String> = emptyList() monarchy.doWithRealm { realm -> userIds = if (allActive) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index 6a57d94677dddcdfd5c48b964883e6347d92d6f4..54c9990bf623ffaf4b3ea88cb3488f264c67c7c9 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -103,6 +103,7 @@ import org.matrix.android.sdk.internal.task.TaskThread import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.task.launchToCallback import org.matrix.android.sdk.internal.util.JsonCanonicalizer +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.olm.OlmManager import timber.log.Timber import java.util.concurrent.atomic.AtomicBoolean @@ -130,6 +131,7 @@ internal class DefaultCryptoService @Inject constructor( private val userId: String, @DeviceId private val deviceId: String?, + private val clock: Clock, private val myDeviceInfoHolder: Lazy<MyDeviceInfoHolder>, // the crypto store private val cryptoStore: IMXCryptoStore, @@ -701,11 +703,11 @@ internal class DefaultCryptoService @Inject constructor( } val safeAlgorithm = alg if (safeAlgorithm != null) { - val t0 = System.currentTimeMillis() + val t0 = clock.epochMillis() Timber.tag(loggerTag.value).v("encryptEventContent() starts") runCatching { val content = safeAlgorithm.encryptEventContent(eventContent, eventType, userIds) - Timber.tag(loggerTag.value).v("## CRYPTO | encryptEventContent() : succeeds after ${System.currentTimeMillis() - t0} ms") + Timber.tag(loggerTag.value).v("## CRYPTO | encryptEventContent() : succeeds after ${clock.epochMillis() - t0} ms") MXEncryptEventContentResult(content, EventType.ENCRYPTED) }.foldToCallback(callback) } else { @@ -1022,9 +1024,9 @@ internal class DefaultCryptoService @Inject constructor( return withContext(coroutineDispatchers.crypto) { Timber.tag(loggerTag.value).v("importRoomKeys starts") - val t0 = System.currentTimeMillis() + val t0 = clock.epochMillis() val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password) - val t1 = System.currentTimeMillis() + val t1 = clock.epochMillis() Timber.tag(loggerTag.value).v("importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms") @@ -1032,7 +1034,7 @@ internal class DefaultCryptoService @Inject constructor( .adapter<List<MegolmSessionData>>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java)) .fromJson(roomKeys) - val t2 = System.currentTimeMillis() + val t2 = clock.epochMillis() Timber.tag(loggerTag.value).v("importRoomKeys : JSON parsing ${t2 - t1} ms") @@ -1224,7 +1226,7 @@ internal class DefaultCryptoService @Inject constructor( // val deviceKey = deviceInfo.identityKey() // // val lastForcedDate = lastNewSessionForcedDates.getObject(senderId, deviceKey) ?: 0 -// val now = System.currentTimeMillis() +// val now = clock.epochMillis() // if (now - lastForcedDate < CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) { // Timber.d("## CRYPTO | markOlmSessionForUnwedging: New session already forced with device at $lastForcedDate. Not forcing another") // return diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt index 6cae2d093586bfaf928e0a6e19656e26d3f83aa3..535999373b8434d21cd0a6c12cfe471b50a0c8ff 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt @@ -31,19 +31,23 @@ import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.sync.SyncTokenStore import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.util.logLimit +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject // Legacy name: MXDeviceList @SessionScope -internal class DeviceListManager @Inject constructor(private val cryptoStore: IMXCryptoStore, - private val olmDevice: MXOlmDevice, - private val syncTokenStore: SyncTokenStore, - private val credentials: Credentials, - private val downloadKeysForUsersTask: DownloadKeysForUsersTask, - private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, - coroutineDispatchers: MatrixCoroutineDispatchers, - private val taskExecutor: TaskExecutor) { +internal class DeviceListManager @Inject constructor( + private val cryptoStore: IMXCryptoStore, + private val olmDevice: MXOlmDevice, + private val syncTokenStore: SyncTokenStore, + private val credentials: Credentials, + private val downloadKeysForUsersTask: DownloadKeysForUsersTask, + private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, + coroutineDispatchers: MatrixCoroutineDispatchers, + private val taskExecutor: TaskExecutor, + private val clock: Clock, +) { interface UserDevicesUpdateListener { fun onUsersDeviceUpdate(userIds: List<String>) @@ -310,9 +314,9 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM stored } else { Timber.v("## CRYPTO | downloadKeys() : starts") - val t0 = System.currentTimeMillis() + val t0 = clock.epochMillis() val result = doKeyDownloadForUsers(downloadUsers) - Timber.v("## CRYPTO | downloadKeys() : doKeyDownloadForUsers succeeds after ${System.currentTimeMillis() - t0} ms") + Timber.v("## CRYPTO | downloadKeys() : doKeyDownloadForUsers succeeds after ${clock.epochMillis() - t0} ms") result.also { it.addEntriesFromMap(stored) } @@ -475,8 +479,10 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM } if (!isVerified) { - Timber.e("## CRYPTO | validateDeviceKeys() : Unable to verify signature on device " + userId + ":" + - deviceKeys.deviceId + " with error " + errorMessage) + Timber.e( + "## CRYPTO | validateDeviceKeys() : Unable to verify signature on device " + userId + ":" + + deviceKeys.deviceId + " with error " + errorMessage + ) return false } @@ -486,9 +492,11 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM // best off sticking with the original keys. // // Should we warn the user about it somehow? - Timber.e("## CRYPTO | validateDeviceKeys() : WARNING:Ed25519 key for device " + userId + ":" + - deviceKeys.deviceId + " has changed : " + - previouslyStoredDeviceKeys.fingerprint() + " -> " + signKey) + Timber.e( + "## CRYPTO | validateDeviceKeys() : WARNING:Ed25519 key for device " + userId + ":" + + deviceKeys.deviceId + " has changed : " + + previouslyStoredDeviceKeys.fingerprint() + " -> " + signKey + ) Timber.e("## CRYPTO | validateDeviceKeys() : $previouslyStoredDeviceKeys -> $deviceKeys") Timber.e("## CRYPTO | validateDeviceKeys() : ${previouslyStoredDeviceKeys.keys} -> ${deviceKeys.keys}") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt index 1c8bce7377c6382d81336a6c20105b626bd70339..a09418964538a74890aa9cd1fa66e9c9809ea4e4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt @@ -36,6 +36,7 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.extensions.foldToCallback import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject @@ -47,6 +48,7 @@ private val loggerTag = LoggerTag("CryptoSyncHandler", LoggerTag.CRYPTO) internal class EventDecryptor @Inject constructor( private val cryptoCoroutineScope: CoroutineScope, private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val clock: Clock, private val roomDecryptorProvider: RoomDecryptorProvider, private val messageEncrypter: MessageEncrypter, private val sendToDeviceTask: SendToDeviceTask, @@ -153,7 +155,7 @@ internal class EventDecryptor @Inject constructor( // we should force start a new session for those Timber.tag(loggerTag.value).v("Unwedging: ${wedgedDevices.size} are wedged") // get the one that should be retried according to rate limit - val now = System.currentTimeMillis() + val now = clock.epochMillis() val toUnwedge = wedgedDevices.filter { val lastForcedDate = lastNewSessionForcedDates[it] ?: 0 if (now - lastForcedDate < DefaultCryptoService.CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingWorkManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingWorkManager.kt index 0013c31eead3319a5977e72d9dad4275bc944328..a2c85e5ceb1e825e5f3d61481d14f3263a160691 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingWorkManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingWorkManager.kt @@ -26,6 +26,7 @@ import org.matrix.android.sdk.internal.di.WorkManagerProvider import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.util.CancelableWork import org.matrix.android.sdk.internal.worker.startChain +import java.util.UUID import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -44,8 +45,8 @@ internal class GossipingWorkManager @Inject constructor( } // Prevent sending queue to stay broken after app restart - // The unique queue id will stay the same as long as this object is instanciated - val queueSuffixApp = System.currentTimeMillis() + // The unique queue id will stay the same as long as this object is instantiated + private val queueSuffixApp = UUID.randomUUID() fun postWork(workRequest: OneTimeWorkRequest, policy: ExistingWorkPolicy = ExistingWorkPolicy.APPEND): Cancelable { workManagerProvider.workManager diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt index a78444dff9ff222d49d8cbc7f3fd9edccff420bf..28ddf291b216d987e785373a4a45eebad1ddf767 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt @@ -75,15 +75,15 @@ internal class InboundGroupSessionStore @Inject constructor( @Synchronized fun getInboundGroupSession(sessionId: String, senderKey: String): InboundGroupSessionHolder? { - val known = sessionCache[CacheKey(sessionId, senderKey)] - Timber.tag(loggerTag.value).v("## Inbound: getInboundGroupSession $sessionId in cache ${known != null}") - return known - ?: store.getInboundGroupSession(sessionId, senderKey)?.also { - Timber.tag(loggerTag.value).v("## Inbound: getInboundGroupSession cache populate ${it.roomId}") - sessionCache.put(CacheKey(sessionId, senderKey), InboundGroupSessionHolder(it)) - }?.let { - InboundGroupSessionHolder(it) - } + val known = sessionCache[CacheKey(sessionId, senderKey)] + Timber.tag(loggerTag.value).v("## Inbound: getInboundGroupSession $sessionId in cache ${known != null}") + return known + ?: store.getInboundGroupSession(sessionId, senderKey)?.also { + Timber.tag(loggerTag.value).v("## Inbound: getInboundGroupSession cache populate ${it.roomId}") + sessionCache.put(CacheKey(sessionId, senderKey), InboundGroupSessionHolder(it)) + }?.let { + InboundGroupSessionHolder(it) + } } @Synchronized diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt index 3a409cf3fdbe4b73e672867e5e568784bbd63697..1612caba9fa55cf3532be20e93e4e4f4bb7f7883 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt @@ -44,6 +44,7 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.android.sdk.internal.worker.WorkerParamsFactory import timber.log.Timber import java.util.concurrent.Executors @@ -59,7 +60,9 @@ internal class IncomingGossipingRequestManager @Inject constructor( private val roomEncryptorsStore: RoomEncryptorsStore, private val roomDecryptorProvider: RoomDecryptorProvider, private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val cryptoCoroutineScope: CoroutineScope) { + private val cryptoCoroutineScope: CoroutineScope, + private val clock: Clock, +) { private val executor = Executors.newSingleThreadExecutor() @@ -89,7 +92,7 @@ internal class IncomingGossipingRequestManager @Inject constructor( fun onVerificationCompleteForDevice(deviceId: String) { // For now we just keep an in memory cache synchronized(recentlyVerifiedDevices) { - recentlyVerifiedDevices[deviceId] = System.currentTimeMillis() + recentlyVerifiedDevices[deviceId] = clock.epochMillis() } } @@ -100,7 +103,7 @@ internal class IncomingGossipingRequestManager @Inject constructor( } if (verifTimestamp == null) return false - val age = System.currentTimeMillis() - verifTimestamp + val age = clock.epochMillis() - verifTimestamp return age < FIVE_MINUTES_IN_MILLIS } @@ -114,11 +117,11 @@ internal class IncomingGossipingRequestManager @Inject constructor( fun onGossipingRequestEvent(event: Event) { val roomKeyShare = event.getClearContent().toModel<GossipingDefaultContent>() Timber.i("## CRYPTO | GOSSIP onGossipingRequestEvent received type ${event.type} from user:${event.senderId}, content:$roomKeyShare") - // val ageLocalTs = event.unsignedData?.age?.let { System.currentTimeMillis() - it } + // val ageLocalTs = event.unsignedData?.age?.let { clock.epochMillis() - it } when (roomKeyShare?.action) { - GossipingToDeviceObject.ACTION_SHARE_REQUEST -> { + GossipingToDeviceObject.ACTION_SHARE_REQUEST -> { if (event.getClearType() == EventType.REQUEST_SECRET) { - IncomingSecretShareRequest.fromEvent(event)?.let { + IncomingSecretShareRequest.fromEvent(event, clock.epochMillis())?.let { if (event.senderId == credentials.userId && it.deviceId == credentials.deviceId) { // ignore, it was sent by me as * Timber.v("## GOSSIP onGossipingRequestEvent type ${event.type} ignore remote echo") @@ -129,7 +132,7 @@ internal class IncomingGossipingRequestManager @Inject constructor( } } } else if (event.getClearType() == EventType.ROOM_KEY_REQUEST) { - IncomingRoomKeyRequest.fromEvent(event)?.let { + IncomingRoomKeyRequest.fromEvent(event, clock.epochMillis())?.let { if (event.senderId == credentials.userId && it.deviceId == credentials.deviceId) { // ignore, it was sent by me as * Timber.v("## GOSSIP onGossipingRequestEvent type ${event.type} ignore remote echo") @@ -141,7 +144,7 @@ internal class IncomingGossipingRequestManager @Inject constructor( } } GossipingToDeviceObject.ACTION_SHARE_CANCELLATION -> { - IncomingRequestCancellation.fromEvent(event)?.let { + IncomingRequestCancellation.fromEvent(event, clock.epochMillis())?.let { receivedRequestCancellations.add(it) } } @@ -346,7 +349,7 @@ internal class IncomingGossipingRequestManager @Inject constructor( val isDeviceLocallyVerified = cryptoStore.getUserDevice(userId, deviceId)?.trustLevel?.isLocallyVerified() when (secretName) { - MASTER_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.master + MASTER_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.master SELF_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.selfSigned USER_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.user KEYBACKUP_SECRET_SSSS_NAME -> cryptoStore.getKeyBackupRecoveryKeyInfo()?.recoveryKey diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt index f8235bf344f7ecf54e336a66c505278877a9236c..89e38cb7cfc418d88f7d1b27bc9d827bd497f2c9 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt @@ -29,6 +29,7 @@ import javax.crypto.spec.SecretKeySpec import kotlin.experimental.and import kotlin.experimental.xor import kotlin.math.min +import kotlin.system.measureTimeMillis /** * Utility class to import/export the crypto data @@ -310,41 +311,41 @@ internal object MXMegolmExportEncryption { */ @Throws(Exception::class) private fun deriveKeys(salt: ByteArray, iterations: Int, password: String): ByteArray { - val t0 = System.currentTimeMillis() - - // based on https://en.wikipedia.org/wiki/PBKDF2 algorithm - // it is simpler than the generic algorithm because the expected key length is equal to the mac key length. - // noticed as dklen/hlen - val prf = Mac.getInstance("HmacSHA512") - prf.init(SecretKeySpec(password.toByteArray(Charsets.UTF_8), "HmacSHA512")) - - // 512 bits key length val key = ByteArray(64) - val uc = ByteArray(64) - - // U1 = PRF(Password, Salt || INT_32_BE(i)) - prf.update(salt) - val int32BE = ByteArray(4) { 0.toByte() } - int32BE[3] = 1.toByte() - prf.update(int32BE) - prf.doFinal(uc, 0) + measureTimeMillis { + // based on https://en.wikipedia.org/wiki/PBKDF2 algorithm + // it is simpler than the generic algorithm because the expected key length is equal to the mac key length. + // noticed as dklen/hlen + val prf = Mac.getInstance("HmacSHA512") + prf.init(SecretKeySpec(password.toByteArray(Charsets.UTF_8), "HmacSHA512")) + + // 512 bits key length + val uc = ByteArray(64) + + // U1 = PRF(Password, Salt || INT_32_BE(i)) + prf.update(salt) + val int32BE = ByteArray(4) { 0.toByte() } + int32BE[3] = 1.toByte() + prf.update(int32BE) + prf.doFinal(uc, 0) - // copy to the key - System.arraycopy(uc, 0, key, 0, uc.size) + // copy to the key + System.arraycopy(uc, 0, key, 0, uc.size) - for (index in 2..iterations) { - // Uc = PRF(Password, Uc-1) - prf.update(uc) - prf.doFinal(uc, 0) + for (index in 2..iterations) { + // Uc = PRF(Password, Uc-1) + prf.update(uc) + prf.doFinal(uc, 0) - // F(Password, Salt, c, i) = U1 ^ U2 ^ ... ^ Uc - for (byteIndex in uc.indices) { - key[byteIndex] = key[byteIndex] xor uc[byteIndex] + // F(Password, Salt, c, i) = U1 ^ U2 ^ ... ^ Uc + for (byteIndex in uc.indices) { + key[byteIndex] = key[byteIndex] xor uc[byteIndex] + } } + }.also { + Timber.v("## deriveKeys() : $iterations in $it ms") } - Timber.v("## deriveKeys() : $iterations in ${System.currentTimeMillis() - t0} ms") - return key } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt index 4947761f05c3ca5e204f6c2c7864d6787c8331f7..7eec83abddf0b501daab4a3cf860567b2d7bae1d 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt @@ -35,6 +35,7 @@ import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.util.JsonCanonicalizer import org.matrix.android.sdk.internal.util.convertFromUTF8 import org.matrix.android.sdk.internal.util.convertToUTF8 +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.olm.OlmAccount import org.matrix.olm.OlmException import org.matrix.olm.OlmMessage @@ -55,7 +56,8 @@ internal class MXOlmDevice @Inject constructor( */ private val store: IMXCryptoStore, private val olmSessionStore: OlmSessionStore, - private val inboundGroupSessionStore: InboundGroupSessionStore + private val inboundGroupSessionStore: InboundGroupSessionStore, + private val clock: Clock, ) { val mutex = Mutex() @@ -277,7 +279,7 @@ internal class MXOlmDevice @Inject constructor( // Pretend we've received a message at this point, otherwise // if we try to send a message to the device, it won't use // this session - olmSessionWrapper.onMessageReceived() + olmSessionWrapper.onMessageReceived(clock.epochMillis()) olmSessionStore.storeSession(olmSessionWrapper, theirIdentityKey) @@ -348,7 +350,7 @@ internal class MXOlmDevice @Inject constructor( val olmSessionWrapper = OlmSessionWrapper(olmSession, 0) // This counts as a received message: set last received message time to now - olmSessionWrapper.onMessageReceived() + olmSessionWrapper.onMessageReceived(clock.epochMillis()) olmSessionStore.storeSession(olmSessionWrapper, theirDeviceIdentityKey) } catch (e: Exception) { @@ -454,7 +456,7 @@ internal class MXOlmDevice @Inject constructor( payloadString = olmSessionWrapper.mutex.withLock { olmSessionWrapper.olmSession.decryptMessage(olmMessage).also { - olmSessionWrapper.onMessageReceived() + olmSessionWrapper.onMessageReceived(clock.epochMillis()) } } olmSessionStore.storeSession(olmSessionWrapper, theirDeviceIdentityKey) @@ -520,6 +522,7 @@ internal class MXOlmDevice @Inject constructor( return MXOutboundSessionInfo( sessionId = sessionId, sharedWithHelper = SharedWithHelper(roomId, sessionId, store), + clock, restoredOutboundGroupSession.creationTime ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt index f4fbca6a0fe5bc7a29cc5f2f7eacf8d366e0c3a6..aac6f67aea1ea95dd0aa698b4160865986b5f336 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmSessionStore.kt @@ -66,7 +66,8 @@ internal class OlmSessionStore @Inject constructor(private val store: IMXCryptoS olmSessions.getOrPut(deviceKey) { mutableListOf() }.forEach { cached -> getSafeSessionIdentifier(cached.olmSession)?.let { cachedSessionId -> if (!persistedKnownSessions.contains(cachedSessionId)) { - persistedKnownSessions.add(cachedSessionId) + // as it's in cache put in on top + persistedKnownSessions.add(0, cachedSessionId) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OneTimeKeysUploader.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OneTimeKeysUploader.kt index 792c9a25dcdb3d1a484417b37bbc73277b2a64fe..8143e36892e50f9bbb9c9e4c37c870c0c00b62a1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OneTimeKeysUploader.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OneTimeKeysUploader.kt @@ -23,6 +23,7 @@ import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.util.JsonCanonicalizer +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.olm.OlmAccount import timber.log.Timber import javax.inject.Inject @@ -38,6 +39,7 @@ internal class OneTimeKeysUploader @Inject constructor( private val olmDevice: MXOlmDevice, private val objectSigner: ObjectSigner, private val uploadKeysTask: UploadKeysTask, + private val clock: Clock, context: Context ) { // tell if there is a OTK check in progress @@ -77,7 +79,7 @@ internal class OneTimeKeysUploader @Inject constructor( Timber.v("maybeUploadOneTimeKeys: already in progress") return } - if (System.currentTimeMillis() - lastOneTimeKeyCheck < ONE_TIME_KEY_UPLOAD_PERIOD) { + if (clock.epochMillis() - lastOneTimeKeyCheck < ONE_TIME_KEY_UPLOAD_PERIOD) { // we've done a key upload recently. Timber.v("maybeUploadOneTimeKeys: executed too recently") return @@ -94,7 +96,7 @@ internal class OneTimeKeysUploader @Inject constructor( Timber.d("maybeUploadOneTimeKeys: otk count $oneTimeKeyCountFromSync , unpublished fallback key ${olmDevice.hasUnpublishedFallbackKey()}") - lastOneTimeKeyCheck = System.currentTimeMillis() + lastOneTimeKeyCheck = clock.epochMillis() // We then check how many keys we can store in the Account object. val maxOneTimeKeys = olmDevice.getMaxNumberOfOneTimeKeys() @@ -126,7 +128,7 @@ internal class OneTimeKeysUploader @Inject constructor( // Check if we need to forget a fallback key val latestPublishedTime = getLastFallbackKeyPublishTime() - if (latestPublishedTime != 0L && System.currentTimeMillis() - latestPublishedTime > FALLBACK_KEY_FORGET_DELAY) { + if (latestPublishedTime != 0L && clock.epochMillis() - latestPublishedTime > FALLBACK_KEY_FORGET_DELAY) { // This should be called once you are reasonably certain that you will not receive any more messages // that use the old fallback key Timber.d("## forgetFallbackKey()") @@ -168,7 +170,7 @@ internal class OneTimeKeysUploader @Inject constructor( olmDevice.markKeysAsPublished() if (hadUnpublishedFallbackKey) { // It had an unpublished fallback key that was published just now - saveLastFallbackKeyPublishTime(System.currentTimeMillis()) + saveLastFallbackKeyPublishTime(clock.epochMillis()) } if (response.hasOneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE)) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt index dbdea9741107897cb1d6b1648b145a1b11f22b5b..3b43ad672b57e0544918e0d0b484d6aee3ebadb1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt @@ -35,13 +35,14 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId import org.matrix.android.sdk.internal.session.SessionComponent +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker import org.matrix.android.sdk.internal.worker.SessionWorkerParams import timber.log.Timber import javax.inject.Inject internal class SendGossipRequestWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<SendGossipRequestWorker.Params>(context, params, sessionManager, Params::class.java) { + SessionSafeCoroutineWorker<SendGossipRequestWorker.Params>(context, params, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( @@ -57,6 +58,7 @@ internal class SendGossipRequestWorker(context: Context, params: WorkerParameter @Inject lateinit var sendToDeviceTask: SendToDeviceTask @Inject lateinit var cryptoStore: IMXCryptoStore @Inject lateinit var credentials: Credentials + @Inject lateinit var clock: Clock override fun injectWith(injector: SessionComponent) { injector.inject(this) @@ -85,7 +87,7 @@ internal class SendGossipRequestWorker(context: Context, params: WorkerParameter content = toDeviceContent.toContent(), senderId = credentials.userId ).also { - it.ageLocalTs = System.currentTimeMillis() + it.ageLocalTs = clock.epochMillis() }) params.keyShareRequest.recipients.forEach { userToDeviceMap -> @@ -109,7 +111,7 @@ internal class SendGossipRequestWorker(context: Context, params: WorkerParameter content = toDeviceContent.toContent(), senderId = credentials.userId ).also { - it.ageLocalTs = System.currentTimeMillis() + it.ageLocalTs = clock.epochMillis() }) params.secretShareRequest.recipients.forEach { userToDeviceMap -> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt index fd472fe73bc323cadf77f760202aefab4e95b136..113d71d387d40f643a46253273c6937393f8517b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt @@ -34,6 +34,7 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId import org.matrix.android.sdk.internal.session.SessionComponent +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker import org.matrix.android.sdk.internal.worker.SessionWorkerParams import timber.log.Timber @@ -63,6 +64,7 @@ internal class SendGossipWorker( @Inject lateinit var credentials: Credentials @Inject lateinit var messageEncrypter: MessageEncrypter @Inject lateinit var ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction + @Inject lateinit var clock: Clock override fun injectWith(injector: SessionComponent) { injector.inject(this) @@ -129,7 +131,7 @@ internal class SendGossipWorker( content = toDeviceContent.toContent(), senderId = credentials.userId ).also { - it.ageLocalTs = System.currentTimeMillis() + it.ageLocalTs = clock.epochMillis() }) try { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt index f9bcdf2c68091a3c64e9c6df2340b8908bbea3b0..86674b4ac55046bfd9499388e6c0a47973a93f82 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt @@ -26,13 +26,17 @@ import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager import org.matrix.android.sdk.internal.crypto.RoomDecryptorProvider import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXMegolmDecryption import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject -internal class MegolmSessionDataImporter @Inject constructor(private val olmDevice: MXOlmDevice, - private val roomDecryptorProvider: RoomDecryptorProvider, - private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, - private val cryptoStore: IMXCryptoStore) { +internal class MegolmSessionDataImporter @Inject constructor( + private val olmDevice: MXOlmDevice, + private val roomDecryptorProvider: RoomDecryptorProvider, + private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, + private val cryptoStore: IMXCryptoStore, + private val clock: Clock, +) { /** * Import a list of megolm session keys. @@ -47,7 +51,7 @@ internal class MegolmSessionDataImporter @Inject constructor(private val olmDevi fun handle(megolmSessionsData: List<MegolmSessionData>, fromBackup: Boolean, progressListener: ProgressListener?): ImportRoomKeysResult { - val t0 = System.currentTimeMillis() + val t0 = clock.epochMillis() val totalNumbersOfKeys = megolmSessionsData.size var lastProgress = 0 @@ -103,7 +107,7 @@ internal class MegolmSessionDataImporter @Inject constructor(private val olmDevi cryptoStore.markBackupDoneForInboundGroupSessions(olmInboundGroupSessionWrappers) } - val t1 = System.currentTimeMillis() + val t1 = clock.epochMillis() Timber.v("## importMegolmSessionsData : sessions import " + (t1 - t0) + " ms (" + megolmSessionsData.size + " sessions)") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt index f0521942304acb1877e17c4c4cd4b6ad96748c17..b31b5e8a645e055e264fae305769db3535101cc8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt @@ -46,6 +46,7 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.util.JsonCanonicalizer import org.matrix.android.sdk.internal.util.convertToUTF8 +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber private val loggerTag = LoggerTag("MXMegolmEncryption", LoggerTag.CRYPTO) @@ -64,7 +65,8 @@ internal class MXMegolmEncryption( private val messageEncrypter: MessageEncrypter, private val warnOnUnknownDevicesRepository: WarnOnUnknownDeviceRepository, private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val cryptoCoroutineScope: CoroutineScope + private val cryptoCoroutineScope: CoroutineScope, + private val clock: Clock, ) : IMXEncrypting, IMXGroupEncryption { // OutboundSessionInfo. Null if we haven't yet started setting one up. Note @@ -86,11 +88,11 @@ internal class MXMegolmEncryption( override suspend fun encryptEventContent(eventContent: Content, eventType: String, userIds: List<String>): Content { - val ts = System.currentTimeMillis() + val ts = clock.epochMillis() Timber.tag(loggerTag.value).v("encryptEventContent : getDevicesInRoom") val devices = getDevicesInRoom(userIds) Timber.tag(loggerTag.value).d("encrypt event in room=$roomId - devices count in room ${devices.allowedDevices.toDebugCount()}") - Timber.tag(loggerTag.value).v("encryptEventContent ${System.currentTimeMillis() - ts}: getDevicesInRoom ${devices.allowedDevices.toDebugString()}") + Timber.tag(loggerTag.value).v("encryptEventContent ${clock.epochMillis() - ts}: getDevicesInRoom ${devices.allowedDevices.toDebugString()}") val outboundSession = ensureOutboundSession(devices.allowedDevices) return encryptContent(outboundSession, eventType, eventContent) @@ -99,7 +101,7 @@ internal class MXMegolmEncryption( // annoyingly we have to serialize again the saved outbound session to store message index :/ // if not we would see duplicate message index errors olmDevice.storeOutboundGroupSessionForRoom(roomId, outboundSession.sessionId) - Timber.tag(loggerTag.value).d("encrypt event in room=$roomId Finished in ${System.currentTimeMillis() - ts} millis") + Timber.tag(loggerTag.value).d("encrypt event in room=$roomId Finished in ${clock.epochMillis() - ts} millis") } } @@ -125,14 +127,14 @@ internal class MXMegolmEncryption( } override suspend fun preshareKey(userIds: List<String>) { - val ts = System.currentTimeMillis() + val ts = clock.epochMillis() Timber.tag(loggerTag.value).d("preshareKey started in $roomId ...") val devices = getDevicesInRoom(userIds) val outboundSession = ensureOutboundSession(devices.allowedDevices) notifyWithheldForSession(devices.withHeldDevices, outboundSession) - Timber.tag(loggerTag.value).d("preshareKey in $roomId done in ${System.currentTimeMillis() - ts} millis") + Timber.tag(loggerTag.value).d("preshareKey in $roomId done in ${clock.epochMillis() - ts} millis") } /** @@ -148,12 +150,14 @@ internal class MXMegolmEncryption( "ed25519" to olmDevice.deviceEd25519Key!! ) - olmDevice.addInboundGroupSession(sessionId!!, olmDevice.getSessionKey(sessionId)!!, roomId, olmDevice.deviceCurve25519Key!!, - emptyList(), keysClaimedMap, false) + olmDevice.addInboundGroupSession( + sessionId!!, olmDevice.getSessionKey(sessionId)!!, roomId, olmDevice.deviceCurve25519Key!!, + emptyList(), keysClaimedMap, false + ) defaultKeysBackupService.maybeBackupKeys() - return MXOutboundSessionInfo(sessionId, SharedWithHelper(roomId, sessionId, cryptoStore)) + return MXOutboundSessionInfo(sessionId, SharedWithHelper(roomId, sessionId, cryptoStore), clock) } /** @@ -243,12 +247,12 @@ internal class MXMegolmEncryption( payload["type"] = EventType.ROOM_KEY payload["content"] = submap - var t0 = System.currentTimeMillis() + var t0 = clock.epochMillis() Timber.tag(loggerTag.value).v("shareUserDevicesKey() : starts") val results = ensureOlmSessionsForDevicesAction.handle(devicesByUser) Timber.tag(loggerTag.value).v( - """shareUserDevicesKey(): ensureOlmSessionsForDevices succeeds after ${System.currentTimeMillis() - t0} ms""" + """shareUserDevicesKey(): ensureOlmSessionsForDevices succeeds after ${clock.epochMillis() - t0} ms""" .trimMargin() ) val contentMap = MXUsersDevicesMap<Any>() @@ -301,7 +305,7 @@ internal class MXMegolmEncryption( cryptoStore.saveGossipingEvents(gossipingEventBuffer) if (haveTargets) { - t0 = System.currentTimeMillis() + t0 = clock.epochMillis() Timber.tag(loggerTag.value).i("shareUserDevicesKey() ${session.sessionId} : has target") Timber.tag(loggerTag.value).d("sending to device room key for ${session.sessionId} to ${contentMap.toDebugString()}") val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, contentMap) @@ -309,7 +313,7 @@ internal class MXMegolmEncryption( withContext(coroutineDispatchers.io) { sendToDeviceTask.execute(sendToDeviceParams) } - Timber.tag(loggerTag.value).i("shareUserDevicesKey() : sendToDevice succeeds after ${System.currentTimeMillis() - t0} ms") + Timber.tag(loggerTag.value).i("shareUserDevicesKey() : sendToDevice succeeds after ${clock.epochMillis() - t0} ms") } catch (failure: Throwable) { // What to do here... Timber.tag(loggerTag.value).e("shareUserDevicesKey() : Failed to share <${session.sessionId}>") @@ -334,7 +338,8 @@ internal class MXMegolmEncryption( senderKey: String?, code: WithHeldCode) { Timber.tag(loggerTag.value).d("notifyKeyWithHeld() :sending withheld for session:$sessionId and code $code to" + - " ${targets.joinToString { "${it.userId}|${it.deviceId}" }}") + " ${targets.joinToString { "${it.userId}|${it.deviceId}" }}" + ) val withHeldContent = RoomKeyWithHeldContent( roomId = roomId, senderKey = senderKey, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt index 136fdc05f5162d9e3e2ff8e1842eaf52adceec47..4225d604aae52e8cf5dfb07053e5ac5acbe9f105 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryptionFactory.kt @@ -28,6 +28,7 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.util.time.Clock import javax.inject.Inject internal class MXMegolmEncryptionFactory @Inject constructor( @@ -42,7 +43,9 @@ internal class MXMegolmEncryptionFactory @Inject constructor( private val messageEncrypter: MessageEncrypter, private val warnOnUnknownDevicesRepository: WarnOnUnknownDeviceRepository, private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val cryptoCoroutineScope: CoroutineScope) { + private val cryptoCoroutineScope: CoroutineScope, + private val clock: Clock, +) { fun create(roomId: String): MXMegolmEncryption { return MXMegolmEncryption( @@ -58,7 +61,8 @@ internal class MXMegolmEncryptionFactory @Inject constructor( messageEncrypter = messageEncrypter, warnOnUnknownDevicesRepository = warnOnUnknownDevicesRepository, coroutineDispatchers = coroutineDispatchers, - cryptoCoroutineScope = cryptoCoroutineScope + cryptoCoroutineScope = cryptoCoroutineScope, + clock = clock, ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt index 091abd49746f1c5e8dd2889e68bd1b261433b1dc..28d925d8fd5cf3690af003798442a82b00da9483 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt @@ -18,21 +18,24 @@ package org.matrix.android.sdk.internal.crypto.algorithms.megolm import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber internal class MXOutboundSessionInfo( // The id of the session val sessionId: String, val sharedWithHelper: SharedWithHelper, + private val clock: Clock, // When the session was created - private val creationTime: Long = System.currentTimeMillis()) { + private val creationTime: Long = clock.epochMillis(), +) { // Number of times this session has been used var useCount: Int = 0 fun needsRotation(rotationPeriodMsgs: Int, rotationPeriodMs: Int): Boolean { var needsRotation = false - val sessionLifetime = System.currentTimeMillis() - creationTime + val sessionLifetime = clock.epochMillis() - creationTime if (useCount >= rotationPeriodMsgs || sessionLifetime >= rotationPeriodMs) { Timber.v("## needsRotation() : Rotating megolm session after $useCount, ${sessionLifetime}ms") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt index 7fdfd5a2876420745209733f323ed2b3a04a8839..c842c5404151adbcce729b5f4fc24f1d1559c81e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt @@ -33,7 +33,7 @@ internal class MXOlmEncryption( private val messageEncrypter: MessageEncrypter, private val deviceListManager: DeviceListManager, private val ensureOlmSessionsForUsersAction: EnsureOlmSessionsForUsersAction) : - IMXEncrypting { + IMXEncrypting { override suspend fun encryptEventContent(eventContent: Content, eventType: String, userIds: List<String>): Content { // pick the list of recipients based on the membership list. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt index 91b6af6fc3ad845e3e9f8119db198b7b9e1f99bd..65bbb0c4125ef7f5a2f50a5fa1d51f10c75cc4c3 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt @@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileKey import org.matrix.android.sdk.internal.util.base64ToBase64Url import org.matrix.android.sdk.internal.util.base64ToUnpaddedBase64 import org.matrix.android.sdk.internal.util.base64UrlToBase64 +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import java.io.ByteArrayOutputStream import java.io.File @@ -42,8 +43,9 @@ internal object MXEncryptedAttachments { fun encrypt(clearStream: InputStream, outputFile: File, + clock: Clock, progress: ((current: Int, total: Int) -> Unit)): EncryptedFileInfo { - val t0 = System.currentTimeMillis() + val t0 = clock.epochMillis() val secureRandom = SecureRandom() val initVectorBytes = ByteArray(16) { 0.toByte() } @@ -100,7 +102,7 @@ internal object MXEncryptedAttachments { hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))), v = "v2" ) - .also { Timber.v("Encrypt in ${System.currentTimeMillis() - t0}ms") } + .also { Timber.v("Encrypt in ${clock.epochMillis() - t0}ms") } } // fun cipherInputStream(attachmentStream: InputStream, mimetype: String?): Pair<DigestInputStream, EncryptedFileInfo> { @@ -159,8 +161,8 @@ internal object MXEncryptedAttachments { * @param attachmentStream the attachment stream. Will be closed after this method call. * @return the encryption file info */ - fun encryptAttachment(attachmentStream: InputStream): EncryptionResult { - val t0 = System.currentTimeMillis() + fun encryptAttachment(attachmentStream: InputStream, clock: Clock): EncryptionResult { + val t0 = clock.epochMillis() val secureRandom = SecureRandom() // generate a random iv key @@ -221,7 +223,7 @@ internal object MXEncryptedAttachments { ), encryptedByteArray = byteArrayOutputStream.toByteArray() ) - .also { Timber.v("Encrypt in ${System.currentTimeMillis() - t0}ms") } + .also { Timber.v("Encrypt in ${clock.epochMillis() - t0}ms") } } /** @@ -234,14 +236,16 @@ internal object MXEncryptedAttachments { */ fun decryptAttachment(attachmentStream: InputStream?, elementToDecrypt: ElementToDecrypt?, - outputStream: OutputStream): Boolean { + outputStream: OutputStream, + clock: Clock + ): Boolean { // sanity checks if (null == attachmentStream || elementToDecrypt == null) { Timber.e("## decryptAttachment() : null stream") return false } - val t0 = System.currentTimeMillis() + val t0 = clock.epochMillis() try { val key = Base64.decode(base64UrlToBase64(elementToDecrypt.k), Base64.DEFAULT) @@ -279,7 +283,8 @@ internal object MXEncryptedAttachments { return false } - return true.also { Timber.v("Decrypt in ${System.currentTimeMillis() - t0}ms") } + Timber.v("Decrypt in ${clock.epochMillis() - t0} ms") + return true } catch (oom: OutOfMemoryError) { Timber.e(oom, "## decryptAttachment() failed: OOM") } catch (e: Exception) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt index c12879dbeeb7d72221376817a00ae0ac7b85fbd6..4d5b38acbf18fabdd3d3f0537faae556933fe77a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt @@ -26,6 +26,7 @@ import java.util.UUID import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec import kotlin.experimental.xor +import kotlin.system.measureTimeMillis private const val SALT_LENGTH = 32 private const val DEFAULT_ITERATION = 500_000 @@ -91,52 +92,53 @@ internal fun deriveKey(password: String, iterations: Int, progressListener: ProgressListener?): ByteArray { // Note: copied and adapted from MXMegolmExportEncryption - val t0 = System.currentTimeMillis() - // based on https://en.wikipedia.org/wiki/PBKDF2 algorithm // it is simpler than the generic algorithm because the expected key length is equal to the mac key length. // noticed as dklen/hlen - // dklen = 256 - // hlen = 512 - val prf = Mac.getInstance("HmacSHA512") - - prf.init(SecretKeySpec(password.toByteArray(), "HmacSHA512")) - // 256 bits key length val dk = ByteArray(32) - val uc = ByteArray(64) - // U1 = PRF(Password, Salt || INT_32_BE(i)) with i goes from 1 to dklen/hlen - prf.update(salt.toByteArray()) - val int32BE = byteArrayOf(0, 0, 0, 1) - prf.update(int32BE) - prf.doFinal(uc, 0) + measureTimeMillis { + // dklen = 256 + // hlen = 512 + val prf = Mac.getInstance("HmacSHA512") - // copy to the key - System.arraycopy(uc, 0, dk, 0, dk.size) + prf.init(SecretKeySpec(password.toByteArray(), "HmacSHA512")) - var lastProgress = -1 + val uc = ByteArray(64) - for (index in 2..iterations) { - // Uc = PRF(Password, Uc-1) - prf.update(uc) + // U1 = PRF(Password, Salt || INT_32_BE(i)) with i goes from 1 to dklen/hlen + prf.update(salt.toByteArray()) + val int32BE = byteArrayOf(0, 0, 0, 1) + prf.update(int32BE) prf.doFinal(uc, 0) - // F(Password, Salt, c, i) = U1 ^ U2 ^ ... ^ Uc - for (byteIndex in dk.indices) { - dk[byteIndex] = dk[byteIndex] xor uc[byteIndex] - } + // copy to the key + System.arraycopy(uc, 0, dk, 0, dk.size) - val progress = (index + 1) * 100 / iterations - if (progress != lastProgress) { - lastProgress = progress - progressListener?.onProgress(lastProgress, 100) + var lastProgress = -1 + + for (index in 2..iterations) { + // Uc = PRF(Password, Uc-1) + prf.update(uc) + prf.doFinal(uc, 0) + + // F(Password, Salt, c, i) = U1 ^ U2 ^ ... ^ Uc + for (byteIndex in dk.indices) { + dk[byteIndex] = dk[byteIndex] xor uc[byteIndex] + } + + val progress = (index + 1) * 100 / iterations + if (progress != lastProgress) { + lastProgress = progress + progressListener?.onProgress(lastProgress, 100) + } } + }.also { + Timber.v("KeysBackupPassword: deriveKeys() : $iterations in $it ms") } - Timber.v("KeysBackupPassword: deriveKeys() : " + iterations + " in " + (System.currentTimeMillis() - t0) + " ms") - return dk } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt index 927d049eca9c13a325f786b5b881c53b0e720637..d7ce553f39aebfbba1f97fbb4161edc6987bcb31 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt @@ -34,7 +34,7 @@ internal data class OlmSessionWrapper( /** * Notify that a message has been received on this olm session so that it updates `lastReceivedMessageTs` */ - fun onMessageReceived() { - lastReceivedMessageTs = System.currentTimeMillis() + fun onMessageReceived(currentTimeMillis: Long) { + lastReceivedMessageTs = currentTimeMillis } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt index 19e66635c748812168e67d3d8b4c3e6b454ec39e..8c877593e74424183ce18b0e8510d198a36b688a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt @@ -66,7 +66,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( key: SsssKeySpec?, keyName: String, keySigner: KeySigner?): SsssKeyCreationInfo { - return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.main) { + return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) { val bytes = (key as? RawBytesKeySpec)?.privateKey ?: ByteArray(32).also { SecureRandom().nextBytes(it) @@ -99,7 +99,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( passphrase: String, keySigner: KeySigner, progressListener: ProgressListener?): SsssKeyCreationInfo { - return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.main) { + return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) { val privatePart = generatePrivateKeyWithPassword(passphrase, progressListener) val storageKeyContent = SecretStorageKeyContent( @@ -158,7 +158,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( } override suspend fun storeSecret(name: String, secretBase64: String, keys: List<SharedSecretStorageService.KeyRef>) { - withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.main) { + withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) { val encryptedContents = HashMap<String, EncryptedSecretContent>() keys.forEach { val keyId = it.keyId @@ -174,7 +174,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( throw SharedSecretStorageError.UnknownAlgorithm(key.keyInfo.content.algorithm ?: "") } } - is KeyInfoResult.Error -> throw key.error + is KeyInfoResult.Error -> throw key.error } } @@ -316,7 +316,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( val algorithm = key.keyInfo.content if (SSSS_ALGORITHM_CURVE25519_AES_SHA2 == algorithm.algorithm) { val keySpec = secretKey as? RawBytesKeySpec ?: throw SharedSecretStorageError.BadKeyFormat - return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.main) { + return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) { // decrypt from recovery key withOlmDecryption { olmPkDecryption -> olmPkDecryption.setPrivateKey(keySpec.privateKey) @@ -331,7 +331,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( } } else if (SSSS_ALGORITHM_AES_HMAC_SHA2 == algorithm.algorithm) { val keySpec = secretKey as? RawBytesKeySpec ?: throw SharedSecretStorageError.BadKeyFormat - return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.main) { + return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) { decryptAesHmacSha2(keySpec, name, secretContent) } } else { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt index 99adbbfbae00615d4bb5f05fa051b6413bf53e96..a509315e7af28f04a9f07c2ed585aae6546659b5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt @@ -97,6 +97,7 @@ import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.extensions.clearWith import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.olm.OlmAccount import org.matrix.olm.OlmException import org.matrix.olm.OlmOutboundGroupSession @@ -110,7 +111,8 @@ internal class RealmCryptoStore @Inject constructor( @CryptoDatabase private val realmConfiguration: RealmConfiguration, private val crossSigningKeysMapper: CrossSigningKeysMapper, @UserId private val userId: String, - @DeviceId private val deviceId: String? + @DeviceId private val deviceId: String?, + private val clock: Clock, ) : IMXCryptoStore { /* ========================================================================================== @@ -307,7 +309,7 @@ internal class RealmCryptoStore @Inject constructor( // Add the device Timber.d("Add device ${cryptoDeviceInfo.deviceId} of user $userId") val newEntity = CryptoMapper.mapToEntity(cryptoDeviceInfo) - newEntity.firstTimeSeenLocalTs = System.currentTimeMillis() + newEntity.firstTimeSeenLocalTs = clock.epochMillis() userEntity.devices.add(newEntity) } else { // Update the device @@ -715,6 +717,7 @@ internal class RealmCryptoStore @Inject constructor( return doWithRealm(realmConfiguration) { it.where<OlmSessionEntity>() .equalTo(OlmSessionEntityFields.DEVICE_KEY, deviceKey) + .sort(OlmSessionEntityFields.LAST_RECEIVED_MESSAGE_TS, Sort.DESCENDING) .findAll() .mapNotNull { sessionEntity -> sessionEntity.sessionId @@ -791,7 +794,7 @@ internal class RealmCryptoStore @Inject constructor( if (outboundGroupSession != null) { val info = realm.createObject(OutboundGroupSessionInfoEntity::class.java).apply { - creationTime = System.currentTimeMillis() + creationTime = clock.epochMillis() putOutboundGroupSession(outboundGroupSession) } entity.outboundSessionInfo = info @@ -881,7 +884,8 @@ internal class RealmCryptoStore @Inject constructor( try { val key = OlmInboundGroupSessionEntity.createPrimaryKey( olmInboundGroupSessionWrapper.olmInboundGroupSession?.sessionIdentifier(), - olmInboundGroupSessionWrapper.senderKey) + olmInboundGroupSessionWrapper.senderKey + ) it.where<OlmInboundGroupSessionEntity>() .equalTo(OlmInboundGroupSessionEntityFields.PRIMARY_KEY, key) @@ -1056,13 +1060,16 @@ internal class RealmCryptoStore @Inject constructor( localCreationTimestamp = 0 ) } - return monarchy.findAllPagedWithChanges(realmDataSourceFactory, - LivePagedListBuilder(dataSourceFactory, + return monarchy.findAllPagedWithChanges( + realmDataSourceFactory, + LivePagedListBuilder( + dataSourceFactory, PagedList.Config.Builder() .setPageSize(20) .setEnablePlaceholders(false) .setPrefetchDistance(1) - .build()) + .build() + ) ) } @@ -1071,13 +1078,16 @@ internal class RealmCryptoStore @Inject constructor( realm.where<GossipingEventEntity>().sort(GossipingEventEntityFields.AGE_LOCAL_TS, Sort.DESCENDING) } val dataSourceFactory = realmDataSourceFactory.map { it.toModel() } - val trail = monarchy.findAllPagedWithChanges(realmDataSourceFactory, - LivePagedListBuilder(dataSourceFactory, + val trail = monarchy.findAllPagedWithChanges( + realmDataSourceFactory, + LivePagedListBuilder( + dataSourceFactory, PagedList.Config.Builder() .setPageSize(20) .setEnablePlaceholders(false) .setPrefetchDistance(1) - .build()) + .build() + ) ) return trail } @@ -1152,7 +1162,7 @@ internal class RealmCryptoStore @Inject constructor( override fun saveGossipingEvents(events: List<Event>) { monarchy.writeAsync { realm -> - val now = System.currentTimeMillis() + val now = clock.epochMillis() events.forEach { event -> val ageLocalTs = event.unsignedData?.age?.let { now - it } ?: now val entity = GossipingEventEntity( @@ -1325,7 +1335,7 @@ internal class RealmCryptoStore @Inject constructor( .findAll() .mapNotNull { entity -> when (entity.type) { - GossipRequestType.KEY -> { + GossipRequestType.KEY -> { IncomingRoomKeyRequest( userId = entity.otherUserId, deviceId = entity.otherDeviceId, @@ -1358,7 +1368,7 @@ internal class RealmCryptoStore @Inject constructor( it.otherUserId = request.userId it.requestId = request.requestId ?: "" it.requestState = GossipingRequestState.PENDING - it.localCreationTimestamp = ageLocalTS ?: System.currentTimeMillis() + it.localCreationTimestamp = ageLocalTS ?: clock.epochMillis() if (request is IncomingSecretShareRequest) { it.type = GossipRequestType.SECRET it.requestedInfoStr = request.secretName @@ -1379,7 +1389,7 @@ internal class RealmCryptoStore @Inject constructor( it.otherUserId = request.userId it.requestId = request.requestId ?: "" it.requestState = GossipingRequestState.PENDING - it.localCreationTimestamp = request.localCreationTimestamp ?: System.currentTimeMillis() + it.localCreationTimestamp = request.localCreationTimestamp ?: clock.epochMillis() if (request is IncomingSecretShareRequest) { it.type = GossipRequestType.SECRET it.requestedInfoStr = request.secretName @@ -1535,13 +1545,16 @@ internal class RealmCryptoStore @Inject constructor( it.toOutgoingGossipingRequest() as? OutgoingRoomKeyRequest ?: OutgoingRoomKeyRequest(requestBody = null, requestId = "?", recipients = emptyMap(), state = OutgoingGossipingRequestState.CANCELLED) } - val trail = monarchy.findAllPagedWithChanges(realmDataSourceFactory, - LivePagedListBuilder(dataSourceFactory, + val trail = monarchy.findAllPagedWithChanges( + realmDataSourceFactory, + LivePagedListBuilder( + dataSourceFactory, PagedList.Config.Builder() .setPageSize(20) .setEnablePlaceholders(false) .setPrefetchDistance(1) - .build()) + .build() + ) ) return trail } @@ -1706,7 +1719,7 @@ internal class RealmCryptoStore @Inject constructor( * So we need to tidy up a bit */ override fun tidyUpDataBase() { - val prevWeekTs = System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1_000 + val prevWeekTs = clock.epochMillis() - 7 * 24 * 60 * 60 * 1_000 doRealmTransaction(realmConfiguration) { realm -> // Only keep one week history diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt index cac649948685b08c3ad76d480e38d5c9e3dd106b..32f24c5d2e7897c92f5017315ee6ada4d7e50cb2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt @@ -33,10 +33,13 @@ import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo013 import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo014 import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo015 +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject -internal class RealmCryptoStoreMigration @Inject constructor() : RealmMigration { +internal class RealmCryptoStoreMigration @Inject constructor( + private val clock: Clock, +) : RealmMigration { /** * Forces all RealmCryptoStoreMigration instances to be equal * Avoids Realm throwing when multiple instances of the migration are set @@ -59,7 +62,7 @@ internal class RealmCryptoStoreMigration @Inject constructor() : RealmMigration if (oldVersion < 5) MigrateCryptoTo005(realm).perform() if (oldVersion < 6) MigrateCryptoTo006(realm).perform() if (oldVersion < 7) MigrateCryptoTo007(realm).perform() - if (oldVersion < 8) MigrateCryptoTo008(realm).perform() + if (oldVersion < 8) MigrateCryptoTo008(realm, clock).perform() if (oldVersion < 9) MigrateCryptoTo009(realm).perform() if (oldVersion < 10) MigrateCryptoTo010(realm).perform() if (oldVersion < 11) MigrateCryptoTo011(realm).perform() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo008.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo008.kt index 785e6a04f42a6fe8ee02ce534b8ea3f92c929c83..ad195e6e555ba72a3c72d96a0512540a236b19ef 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo008.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo008.kt @@ -21,8 +21,12 @@ import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator +import org.matrix.android.sdk.internal.util.time.Clock -internal class MigrateCryptoTo008(realm: DynamicRealm) : RealmMigrator(realm, 8) { +internal class MigrateCryptoTo008( + realm: DynamicRealm, + private val clock: Clock, +) : RealmMigrator(realm, 8) { override fun doMigrate(realm: DynamicRealm) { realm.schema.create("MyDeviceLastSeenInfoEntity") @@ -33,7 +37,7 @@ internal class MigrateCryptoTo008(realm: DynamicRealm) : RealmMigrator(realm, 8) .addField(MyDeviceLastSeenInfoEntityFields.LAST_SEEN_TS, Long::class.java) .setNullable(MyDeviceLastSeenInfoEntityFields.LAST_SEEN_TS, true) - val now = System.currentTimeMillis() + val now = clock.epochMillis() realm.schema.get("DeviceInfoEntity") ?.addField(DeviceInfoEntityFields.FIRST_TIME_SEEN_LOCAL_TS, Long::class.java) ?.setNullable(DeviceInfoEntityFields.FIRST_TIME_SEEN_LOCAL_TS, true) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt index 6167314b5a354db61c9ca734b67bf5cce7b64a43..114a596964fa7228ed15a5db8490f164b321a906 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoRoomEntity.kt @@ -31,8 +31,8 @@ internal open class CryptoRoomEntity( // a security to ensure that a room will never revert to not encrypted // even if a new state event with empty encryption, or state is reset somehow var wasEncryptedOnce: Boolean? = false - ) : - RealmObject() { +) : + RealmObject() { companion object } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmInboundGroupSessionEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmInboundGroupSessionEntity.kt index f330e8822acccc10f40217da6915379a6612f1cc..83671b28d95e387ba48f2b2b9211a4a47c4d5e7d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmInboundGroupSessionEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmInboundGroupSessionEntity.kt @@ -34,7 +34,7 @@ internal open class OlmInboundGroupSessionEntity( var olmInboundGroupSessionData: String? = null, // Indicate if the key has been backed up to the homeserver var backedUp: Boolean = false) : - RealmObject() { + RealmObject() { fun getInboundGroupSession(): OlmInboundGroupSessionWrapper2? { return try { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmSessionEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmSessionEntity.kt index 0b69311c57dea2dd6b4971532b2ebc66a5bc3a7d..1a637d76c4ac8c9dc81fd1e924d4ee4196a39e45 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmSessionEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OlmSessionEntity.kt @@ -30,7 +30,7 @@ internal open class OlmSessionEntity(@PrimaryKey var primaryKey: String = "", var deviceKey: String? = null, var olmSessionData: String? = null, var lastReceivedMessageTs: Long = 0) : - RealmObject() { + RealmObject() { fun getOlmSession(): OlmSession? { return deserializeFromRealm(olmSessionData) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceTask.kt index ca04bac5d5d65ca8f72fef831c4fefa8024f486e..0a77d33accc9710bacbd3233cecc4b4146d72e58 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DeleteDeviceTask.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.crypto.tasks import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor +import org.matrix.android.sdk.api.session.uia.UiaResult import org.matrix.android.sdk.internal.auth.registration.handleUIA import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.rest.DeleteDeviceParams @@ -47,13 +48,13 @@ internal class DefaultDeleteDeviceTask @Inject constructor( } } catch (throwable: Throwable) { if (params.userInteractiveAuthInterceptor == null || - !handleUIA( + handleUIA( failure = throwable, interceptor = params.userInteractiveAuthInterceptor, retryBlock = { authUpdate -> execute(params.copy(userAuthParam = authUpdate)) } - ) + ) != UiaResult.SUCCESS ) { Timber.d("## UIA: propagate failure") throw throwable diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/InitializeCrossSigningTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/InitializeCrossSigningTask.kt index eefdd25044eeef01cd730ac0bb091ddc86b774a7..53190c43ff8105a7c21a873a3b60bd7246f152ad 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/InitializeCrossSigningTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/InitializeCrossSigningTask.kt @@ -20,6 +20,7 @@ import dagger.Lazy import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey import org.matrix.android.sdk.api.session.crypto.crosssigning.KeyUsage +import org.matrix.android.sdk.api.session.uia.UiaResult import org.matrix.android.sdk.api.util.toBase64NoPadding import org.matrix.android.sdk.internal.auth.registration.handleUIA import org.matrix.android.sdk.internal.crypto.MXOlmDevice @@ -126,13 +127,13 @@ internal class DefaultInitializeCrossSigningTask @Inject constructor( uploadSigningKeysTask.execute(uploadSigningKeysParams) } catch (failure: Throwable) { if (params.interactiveAuthInterceptor == null || - !handleUIA( + handleUIA( failure = failure, interceptor = params.interactiveAuthInterceptor, retryBlock = { authUpdate -> uploadSigningKeysTask.execute(uploadSigningKeysParams.copy(userAuthParam = authUpdate)) } - ) + ) != UiaResult.SUCCESS ) { Timber.d("## UIA: propagate failure") throw failure diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultOutgoingSASDefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultOutgoingSASDefaultVerificationTransaction.kt index e203f03b06ff7329bced3394133aa67653b0250e..e0d912a9a62a1e544b3bc8273ec65e736871fac2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultOutgoingSASDefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultOutgoingSASDefaultVerificationTransaction.kt @@ -123,7 +123,7 @@ internal class DefaultOutgoingSASDefaultVerificationTransaction( // val requestMessage = KeyVerificationRequest( // fromDevice = session.sessionParams.deviceId ?: "", // methods = listOf(KeyVerificationStart.VERIF_METHOD_SAS), -// timestamp = System.currentTimeMillis().toInt(), +// timestamp = clock.epochMillis().toInt(), // transactionId = transactionId // ) // diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt index 28bf1d70f7fb09f867916430d93214baae04123c..d62ca5503d953aac844e79b5369213dd9dc92a39 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt @@ -84,6 +84,7 @@ import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.task.TaskExecutor +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import java.util.UUID import javax.inject.Inject @@ -104,7 +105,8 @@ internal class DefaultVerificationService @Inject constructor( private val verificationTransportToDeviceFactory: VerificationTransportToDeviceFactory, private val crossSigningService: CrossSigningService, private val cryptoCoroutineScope: CoroutineScope, - private val taskExecutor: TaskExecutor + private val taskExecutor: TaskExecutor, + private val clock: Clock, ) : DefaultVerificationTransaction.Listener, VerificationService { private val uiHandler = Handler(Looper.getMainLooper()) @@ -261,9 +263,11 @@ internal class DefaultVerificationService @Inject constructor( } override fun markedLocallyAsManuallyVerified(userId: String, deviceID: String) { - setDeviceVerificationAction.handle(DeviceTrustLevel(false, true), + setDeviceVerificationAction.handle( + DeviceTrustLevel(crossSigningVerified = false, locallyVerified = true), userId, - deviceID) + deviceID + ) listeners.forEach { try { @@ -313,7 +317,7 @@ internal class DefaultVerificationService @Inject constructor( val requestsForUser = pendingRequests.getOrPut(senderId) { mutableListOf() } val pendingVerificationRequest = PendingVerificationRequest( - ageLocalTs = event.ageLocalTs ?: System.currentTimeMillis(), + ageLocalTs = event.ageLocalTs ?: clock.epochMillis(), isIncoming = true, otherUserId = senderId, // requestInfo.toUserId, roomId = null, @@ -352,7 +356,7 @@ internal class DefaultVerificationService @Inject constructor( val requestsForUser = pendingRequests.getOrPut(senderId) { mutableListOf() } val pendingVerificationRequest = PendingVerificationRequest( - ageLocalTs = event.ageLocalTs ?: System.currentTimeMillis(), + ageLocalTs = event.ageLocalTs ?: clock.epochMillis(), isIncoming = true, otherUserId = senderId, // requestInfo.toUserId, roomId = event.roomId, @@ -552,7 +556,8 @@ internal class DefaultVerificationService @Inject constructor( myDeviceInfoHolder.get().myDevice.fingerprint()!!, startReq.transactionId, otherUserId, - autoAccept).also { txConfigure(it) } + autoAccept + ).also { txConfigure(it) } addTransaction(tx) tx.onVerificationStart(startReq) return null @@ -644,9 +649,11 @@ internal class DefaultVerificationService @Inject constructor( if (existingRequest != null) { // Mark this request as cancelled - updatePendingRequest(existingRequest.copy( - cancelConclusion = safeValueOf(cancelReq.code) - )) + updatePendingRequest( + existingRequest.copy( + cancelConclusion = safeValueOf(cancelReq.code) + ) + ) } existingTransaction?.state = VerificationTxState.Cancelled(safeValueOf(cancelReq.code), false) @@ -809,15 +816,19 @@ internal class DefaultVerificationService @Inject constructor( ?.let { vt -> val otherDeviceId = vt.otherDeviceId if (!crossSigningService.canCrossSign()) { - outgoingGossipingRequestManager.sendSecretShareRequest(MASTER_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId - ?: "*"))) - outgoingGossipingRequestManager.sendSecretShareRequest(SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId - ?: "*"))) - outgoingGossipingRequestManager.sendSecretShareRequest(USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId - ?: "*"))) + outgoingGossipingRequestManager.sendSecretShareRequest( + MASTER_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")) + ) + outgoingGossipingRequestManager.sendSecretShareRequest( + SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")) + ) + outgoingGossipingRequestManager.sendSecretShareRequest( + USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")) + ) } - outgoingGossipingRequestManager.sendSecretShareRequest(KEYBACKUP_SECRET_SSSS_NAME, mapOf(userId to listOf(otherDeviceId - ?: "*"))) + outgoingGossipingRequestManager.sendSecretShareRequest( + KEYBACKUP_SECRET_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*")) + ) } } } @@ -917,16 +928,19 @@ internal class DefaultVerificationService @Inject constructor( qrCodeData = qrCodeData, userId = userId, deviceId = deviceId ?: "", - isIncoming = false) + isIncoming = false + ) tx.transport = transportCreator.invoke(tx) addTransaction(tx) } - updatePendingRequest(existingRequest.copy( - readyInfo = readyReq - )) + updatePendingRequest( + existingRequest.copy( + readyInfo = readyReq + ) + ) } private fun createQrCodeData(requestId: String?, otherUserId: String, otherDeviceId: String?): QrCodeData? { @@ -1115,7 +1129,8 @@ internal class DefaultVerificationService @Inject constructor( myDeviceInfoHolder.get().myDevice.fingerprint()!!, txID, otherUserId, - otherDeviceId) + otherDeviceId + ) tx.transport = verificationTransportToDeviceFactory.createTransport(tx) addTransaction(tx) @@ -1150,7 +1165,7 @@ internal class DefaultVerificationService @Inject constructor( val validLocalId = localId ?: LocalEcho.createLocalEchoId() val verificationRequest = PendingVerificationRequest( - ageLocalTs = System.currentTimeMillis(), + ageLocalTs = clock.epochMillis(), isIncoming = false, roomId = roomId, localId = validLocalId, @@ -1175,11 +1190,13 @@ internal class DefaultVerificationService @Inject constructor( transport.sendVerificationRequest(methodValues, validLocalId, otherUserId, roomId, null) { syncedId, info -> // We need to update with the syncedID - updatePendingRequest(verificationRequest.copy( - transactionId = syncedId, - // localId stays different - requestInfo = info - )) + updatePendingRequest( + verificationRequest.copy( + transactionId = syncedId, + // localId stays different + requestInfo = info + ) + ) } requestsForUser.add(verificationRequest) @@ -1228,7 +1245,7 @@ internal class DefaultVerificationService @Inject constructor( val verificationRequest = PendingVerificationRequest( transactionId = localId, - ageLocalTs = System.currentTimeMillis(), + ageLocalTs = clock.epochMillis(), isIncoming = false, roomId = null, localId = localId, @@ -1254,10 +1271,12 @@ internal class DefaultVerificationService @Inject constructor( transport.sendVerificationRequest(methodValues, localId, otherUserId, null, targetDevices) { _, info -> // Nothing special to do in to device mode - updatePendingRequest(verificationRequest.copy( - // localId stays different - requestInfo = info - )) + updatePendingRequest( + verificationRequest.copy( + // localId stays different + requestInfo = info + ) + ) } requestsForUser.add(verificationRequest) @@ -1271,9 +1290,11 @@ internal class DefaultVerificationService @Inject constructor( .cancelTransaction(transactionId, otherUserId, null, CancelCode.User) getExistingVerificationRequest(otherUserId, transactionId)?.let { - updatePendingRequest(it.copy( - cancelConclusion = CancelCode.User - )) + updatePendingRequest( + it.copy( + cancelConclusion = CancelCode.User + ) + ) } } @@ -1307,7 +1328,8 @@ internal class DefaultVerificationService @Inject constructor( myDeviceInfoHolder.get().myDevice.fingerprint()!!, transactionId, otherUserId, - otherDeviceId) + otherDeviceId + ) tx.transport = verificationTransportRoomMessageFactory.createTransport(roomId, tx) addTransaction(tx) @@ -1333,7 +1355,8 @@ internal class DefaultVerificationService @Inject constructor( otherUserId, existingRequest.requestInfo?.fromDevice ?: "", existingRequest.requestInfo?.methods, - methods) { + methods + ) { verificationTransportRoomMessageFactory.createTransport(roomId, it) } if (methods.isNullOrEmpty()) { @@ -1343,7 +1366,8 @@ internal class DefaultVerificationService @Inject constructor( } // TODO this is not yet related to a transaction, maybe we should use another method like for cancel? val readyMsg = transport.createReady(transactionId, deviceId ?: "", computedMethods) - transport.sendToOther(EventType.KEY_VERIFICATION_READY, + transport.sendToOther( + EventType.KEY_VERIFICATION_READY, readyMsg, VerificationTxState.None, CancelCode.User, @@ -1372,7 +1396,8 @@ internal class DefaultVerificationService @Inject constructor( otherUserId, existingRequest.requestInfo?.fromDevice ?: "", existingRequest.requestInfo?.methods, - methods) { + methods + ) { verificationTransportToDeviceFactory.createTransport(it) } if (methods.isNullOrEmpty()) { @@ -1446,7 +1471,8 @@ internal class DefaultVerificationService @Inject constructor( qrCodeData = qrCodeData, userId = userId, deviceId = deviceId ?: "", - isIncoming = false) + isIncoming = false + ) tx.transport = transportCreator.invoke(tx) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SendVerificationMessageWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SendVerificationMessageWorker.kt index a763c05e07696f6c20ae584214b3930229db840a..0a175ae3ca22a971dab0c84119fde3789b18aa60 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SendVerificationMessageWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SendVerificationMessageWorker.kt @@ -35,7 +35,7 @@ import javax.inject.Inject * Possible next worker : None */ internal class SendVerificationMessageWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<SendVerificationMessageWorker.Params>(context, params, sessionManager, Params::class.java) { + SessionSafeCoroutineWorker<SendVerificationMessageWorker.Params>(context, params, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt index 52166761abbdf02b43a0e7767676a6adcf3781e2..ec4e1aa65cb58ac337f8345286ebb16723c515f6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt @@ -34,11 +34,13 @@ import org.matrix.android.sdk.internal.database.model.EventInsertType import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject internal class VerificationMessageProcessor @Inject constructor( private val eventDecryptor: EventDecryptor, + private val clock: Clock, private val verificationService: DefaultVerificationService, @UserId private val userId: String, @DeviceId private val deviceId: String? @@ -71,8 +73,7 @@ internal class VerificationMessageProcessor @Inject constructor( // If the request is in the future by more than 5 minutes or more than 10 minutes in the past, // the message should be ignored by the receiver. - if (!VerificationService.isValidRequest(event.ageLocalTs - ?: event.originServerTs)) return Unit.also { + if (!VerificationService.isValidRequest(event.ageLocalTs ?: event.originServerTs, clock.epochMillis())) return Unit.also { Timber.d("## SAS Verification live observer: msgId: ${event.eventId} is outdated") } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessage.kt index bd1186908c4cdcd70a802700d14bc2c005d89cdd..325a6f0ba2daef51f2dbc5914a1bce98d31de627 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessage.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessage.kt @@ -47,6 +47,7 @@ import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_REC import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS import org.matrix.android.sdk.internal.di.WorkManagerProvider import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker import org.matrix.android.sdk.internal.worker.WorkerParamsFactory import timber.log.Timber @@ -61,7 +62,8 @@ internal class VerificationTransportRoomMessage( private val roomId: String, private val localEchoEventFactory: LocalEchoEventFactory, private val tx: DefaultVerificationTransaction?, - private val coroutineScope: CoroutineScope + private val coroutineScope: CoroutineScope, + private val clock: Clock, ) : VerificationTransport { override fun <T> sendToOther(type: String, @@ -77,10 +79,12 @@ internal class VerificationTransportRoomMessage( content = verificationInfo.toEventContent()!! ) - val workerParams = WorkerParamsFactory.toData(SendVerificationMessageWorker.Params( - sessionId = sessionId, - eventId = event.eventId ?: "" - )) + val workerParams = WorkerParamsFactory.toData( + SendVerificationMessageWorker.Params( + sessionId = sessionId, + eventId = event.eventId ?: "" + ) + ) val enqueueInfo = enqueueSendWork(workerParams) // I cannot just listen to the given work request, because when used in a uniqueWork, @@ -155,7 +159,7 @@ internal class VerificationTransportRoomMessage( transactionId = "", fromDevice = userDeviceId ?: "", methods = supportedMethods, - timestamp = System.currentTimeMillis() + timestamp = clock.epochMillis() ) val info = MessageVerificationRequestContent( @@ -175,10 +179,12 @@ internal class VerificationTransportRoomMessage( content ) - val workerParams = WorkerParamsFactory.toData(SendVerificationMessageWorker.Params( - sessionId = sessionId, - eventId = event.eventId ?: "" - )) + val workerParams = WorkerParamsFactory.toData( + SendVerificationMessageWorker.Params( + sessionId = sessionId, + eventId = event.eventId ?: "" + ) + ) val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder<SendVerificationMessageWorker>() .setConstraints(WorkManagerProvider.workConstraints) @@ -230,10 +236,12 @@ internal class VerificationTransportRoomMessage( roomId = roomId, content = MessageVerificationCancelContent.create(transactionId, code).toContent() ) - val workerParams = WorkerParamsFactory.toData(SendVerificationMessageWorker.Params( - sessionId = sessionId, - eventId = event.eventId ?: "" - )) + val workerParams = WorkerParamsFactory.toData( + SendVerificationMessageWorker.Params( + sessionId = sessionId, + eventId = event.eventId ?: "" + ) + ) enqueueSendWork(workerParams) } @@ -250,10 +258,12 @@ internal class VerificationTransportRoomMessage( ) ).toContent() ) - val workerParams = WorkerParamsFactory.toData(SendVerificationMessageWorker.Params( - sessionId = sessionId, - eventId = event.eventId ?: "" - )) + val workerParams = WorkerParamsFactory.toData( + SendVerificationMessageWorker.Params( + sessionId = sessionId, + eventId = event.eventId ?: "" + ) + ) val enqueueInfo = enqueueSendWork(workerParams) val workLiveData = workManagerProvider.workManager @@ -296,13 +306,13 @@ internal class VerificationTransportRoomMessage( messageAuthenticationCode: String, shortAuthenticationStrings: List<String>): VerificationInfoAccept = MessageVerificationAcceptContent.create( - tid, - keyAgreementProtocol, - hash, - commitment, - messageAuthenticationCode, - shortAuthenticationStrings - ) + tid, + keyAgreementProtocol, + hash, + commitment, + messageAuthenticationCode, + shortAuthenticationStrings + ) override fun createKey(tid: String, pubKey: String): VerificationInfoKey = MessageVerificationKeyContent.create(tid, pubKey) @@ -361,7 +371,7 @@ internal class VerificationTransportRoomMessage( private fun createEventAndLocalEcho(localId: String = LocalEcho.createLocalEchoId(), type: String, roomId: String, content: Content): Event { return Event( roomId = roomId, - originServerTs = System.currentTimeMillis(), + originServerTs = clock.epochMillis(), senderId = userId, eventId = localId, type = type, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessageFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessageFactory.kt index f89127273b8d0ced5ada3d5277155bf986290425..b1b7ad7a98eb34cbf85ff214e5cef255d271ec2b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessageFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportRoomMessageFactory.kt @@ -22,6 +22,7 @@ import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.WorkManagerProvider import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory import org.matrix.android.sdk.internal.task.TaskExecutor +import org.matrix.android.sdk.internal.util.time.Clock import javax.inject.Inject internal class VerificationTransportRoomMessageFactory @Inject constructor( @@ -33,17 +34,21 @@ internal class VerificationTransportRoomMessageFactory @Inject constructor( @DeviceId private val deviceId: String?, private val localEchoEventFactory: LocalEchoEventFactory, - private val taskExecutor: TaskExecutor + private val taskExecutor: TaskExecutor, + private val clock: Clock, ) { fun createTransport(roomId: String, tx: DefaultVerificationTransaction?): VerificationTransportRoomMessage { - return VerificationTransportRoomMessage(workManagerProvider, + return VerificationTransportRoomMessage( + workManagerProvider, sessionId, userId, deviceId, roomId, localEchoEventFactory, tx, - taskExecutor.executorScope) + taskExecutor.executorScope, + clock + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt index 40deda2745531dbab494a28a32e8c93a1a6c3f19..bc24ef2966ef5e6b9549517568b973430328d58b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt @@ -35,13 +35,16 @@ import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.configureWith +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber +// TODO var could be val internal class VerificationTransportToDevice( private var tx: DefaultVerificationTransaction?, private var sendToDeviceTask: SendToDeviceTask, private val myDeviceId: String?, - private var taskExecutor: TaskExecutor + private var taskExecutor: TaskExecutor, + private val clock: Clock, ) : VerificationTransport { override fun sendVerificationRequest(supportedMethods: List<String>, @@ -56,7 +59,7 @@ internal class VerificationTransportToDevice( transactionId = localId, fromDevice = myDeviceId ?: "", methods = supportedMethods, - timestamp = System.currentTimeMillis() + timestamp = clock.epochMillis() ) val keyReq = KeyVerificationRequest( fromDevice = validKeyReq.fromDevice, @@ -201,7 +204,8 @@ internal class VerificationTransportToDevice( hash, commitment, messageAuthenticationCode, - shortAuthenticationStrings) + shortAuthenticationStrings + ) override fun createKey(tid: String, pubKey: String): VerificationInfoKey = KeyVerificationKey.create(tid, pubKey) @@ -221,7 +225,8 @@ internal class VerificationTransportToDevice( hashes, messageAuthenticationCodes, shortAuthenticationStrings, - null) + null + ) } override fun createStartForQrCode(fromDevice: String, @@ -235,7 +240,8 @@ internal class VerificationTransportToDevice( null, null, null, - sharedSecret) + sharedSecret + ) } override fun createReady(tid: String, fromDevice: String, methods: List<String>): VerificationInfoReady { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDeviceFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDeviceFactory.kt index e9a2c65ef753323b04414257d5cd3275a5ad7b2d..312d911822a1a28987e70943e7da74dfa726a328 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDeviceFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDeviceFactory.kt @@ -19,14 +19,17 @@ package org.matrix.android.sdk.internal.crypto.verification import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.task.TaskExecutor +import org.matrix.android.sdk.internal.util.time.Clock import javax.inject.Inject internal class VerificationTransportToDeviceFactory @Inject constructor( private val sendToDeviceTask: SendToDeviceTask, @DeviceId val myDeviceId: String?, - private val taskExecutor: TaskExecutor) { + private val taskExecutor: TaskExecutor, + private val clock: Clock, +) { fun createTransport(tx: DefaultVerificationTransaction?): VerificationTransportToDevice { - return VerificationTransportToDevice(tx, sendToDeviceTask, myDeviceId, taskExecutor) + return VerificationTransportToDevice(tx, sendToDeviceTask, myDeviceId, taskExecutor, clock) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/AsyncTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/AsyncTransaction.kt index 315d77d932e3733a7859ec3531c5086ea0746484..7d263f19372f81e9dc2b3513000cde37191d9790 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/AsyncTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/AsyncTransaction.kt @@ -24,6 +24,7 @@ import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber +import kotlin.system.measureTimeMillis internal fun <T> CoroutineScope.asyncTransaction(monarchy: Monarchy, transaction: suspend (realm: Realm) -> T) { asyncTransaction(monarchy.realmConfiguration, transaction) @@ -41,13 +42,13 @@ internal suspend fun <T> awaitTransaction(config: RealmConfiguration, transactio bgRealm.beginTransaction() val result: T try { - val start = System.currentTimeMillis() - result = transaction(bgRealm) - if (isActive) { - bgRealm.commitTransaction() - val end = System.currentTimeMillis() - val time = end - start - Timber.v("Execute transaction in $time millis") + measureTimeMillis { + result = transaction(bgRealm) + if (isActive) { + bgRealm.commitTransaction() + } + }.also { + Timber.v("Execute transaction in $it millis") } } finally { if (bgRealm.isInTransaction) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/EventInsertLiveObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/EventInsertLiveObserver.kt index 115025cc7d88ea5efe9fa71d721bf059b92a49ad..751992fa7f8839c614dd11a2eeb5c219679ef66f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/EventInsertLiveObserver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/EventInsertLiveObserver.kt @@ -19,6 +19,9 @@ package org.matrix.android.sdk.internal.database import com.zhuinden.monarchy.Monarchy import io.realm.RealmConfiguration import io.realm.RealmResults +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import org.matrix.android.sdk.internal.database.mapper.asDomain import org.matrix.android.sdk.internal.database.model.EventEntity @@ -32,16 +35,28 @@ import javax.inject.Inject internal class EventInsertLiveObserver @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration, private val processors: Set<@JvmSuppressWildcards EventInsertLiveProcessor>) : - RealmLiveEntityObserver<EventInsertEntity>(realmConfiguration) { + RealmLiveEntityObserver<EventInsertEntity>(realmConfiguration) { override val query = Monarchy.Query { it.where(EventInsertEntity::class.java).equalTo(EventInsertEntityFields.CAN_BE_PROCESSED, true) } + private val onResultsChangedFlow = MutableSharedFlow<RealmResults<EventInsertEntity>>() + + init { + onResultsChangedFlow + .onEach { handleChange(it) } + .launchIn(observerScope) + } + override fun onChange(results: RealmResults<EventInsertEntity>) { if (!results.isLoaded || results.isEmpty()) { return } + observerScope.launch { onResultsChangedFlow.emit(results) } + } + + private suspend fun handleChange(results: RealmResults<EventInsertEntity>) { val idsToDeleteAfterProcess = ArrayList<String>() val filteredEvents = ArrayList<EventInsertEntity>(results.size) Timber.v("EventInsertEntity updated with ${results.size} results in db") @@ -58,30 +73,29 @@ internal class EventInsertLiveObserver @Inject constructor(@SessionDatabase real } idsToDeleteAfterProcess.add(it.eventId) } - observerScope.launch { - awaitTransaction(realmConfiguration) { realm -> - Timber.v("##Transaction: There are ${filteredEvents.size} events to process ") - filteredEvents.forEach { eventInsert -> - val eventId = eventInsert.eventId - val event = EventEntity.where(realm, eventId).findFirst() - if (event == null) { - Timber.v("Event $eventId not found") - return@forEach - } - val domainEvent = event.asDomain() - processors.filter { - it.shouldProcess(eventId, domainEvent.getClearType(), eventInsert.insertType) - }.forEach { - it.process(realm, domainEvent) - } + + awaitTransaction(realmConfiguration) { realm -> + Timber.v("##Transaction: There are ${filteredEvents.size} events to process ") + filteredEvents.forEach { eventInsert -> + val eventId = eventInsert.eventId + val event = EventEntity.where(realm, eventId).findFirst() + if (event == null) { + Timber.v("Event $eventId not found") + return@forEach + } + val domainEvent = event.asDomain() + processors.filter { + it.shouldProcess(eventId, domainEvent.getClearType(), eventInsert.insertType) + }.forEach { + it.process(realm, domainEvent) } - realm.where(EventInsertEntity::class.java) - .`in`(EventInsertEntityFields.EVENT_ID, idsToDeleteAfterProcess.toTypedArray()) - .findAll() - .deleteAllFromRealm() } - processors.forEach { it.onPostProcess() } + realm.where(EventInsertEntity::class.java) + .`in`(EventInsertEntityFields.EVENT_ID, idsToDeleteAfterProcess.toTypedArray()) + .findAll() + .deleteAllFromRealm() } + processors.forEach { it.onPostProcess() } } private fun shouldProcess(eventInsertEntity: EventInsertEntity): Boolean { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt index 50eb086f9ab47b578294b20ebfe590b6e82c938d..f2f88e216bcc98e7f67d9b564e1c913e1cc4e193 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt @@ -35,7 +35,7 @@ import java.util.concurrent.atomic.AtomicReference internal interface LiveEntityObserver : SessionLifecycleObserver internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val realmConfiguration: RealmConfiguration) : - LiveEntityObserver, RealmChangeListener<RealmResults<T>> { + LiveEntityObserver, RealmChangeListener<RealmResults<T>> { private companion object { val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionProvider.kt index 8c62c345d0cc75336077a06d722462ae2d9484ce..e5b59155902fae23cfb7111dfd370c0a22c6ec1a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionProvider.kt @@ -33,7 +33,7 @@ import kotlin.concurrent.getOrSet */ @SessionScope internal class RealmSessionProvider @Inject constructor(@SessionDatabase private val monarchy: Monarchy) : - SessionLifecycleObserver { + SessionLifecycleObserver { private val realmThreadLocal = ThreadLocal<Realm>() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index a57397dad5f10595c3c4fa72d1e32ced108f73e2..04a6e83ea17723fee7b5a6ff7aa8efaf9f12e31a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -44,6 +44,8 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo023 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo024 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo025 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo026 +import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo027 +import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo028 import org.matrix.android.sdk.internal.util.Normalizer import timber.log.Timber import javax.inject.Inject @@ -58,7 +60,7 @@ internal class RealmSessionStoreMigration @Inject constructor( override fun equals(other: Any?) = other is RealmSessionStoreMigration override fun hashCode() = 1000 - val schemaVersion = 26L + val schemaVersion = 28L override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { Timber.d("Migrating Realm Session from $oldVersion to $newVersion") @@ -89,5 +91,7 @@ internal class RealmSessionStoreMigration @Inject constructor( if (oldVersion < 24) MigrateSessionTo024(realm).perform() if (oldVersion < 25) MigrateSessionTo025(realm).perform() if (oldVersion < 26) MigrateSessionTo026(realm).perform() + if (oldVersion < 27) MigrateSessionTo027(realm).perform() + if (oldVersion < 28) MigrateSessionTo028(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt index 24de26eeea9e701268181671fb0e35f745536686..d052a7dea497660a8dd83bb7ff9a530d4bf44351 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt @@ -20,6 +20,7 @@ import io.realm.Realm import io.realm.RealmQuery import io.realm.Sort import io.realm.kotlin.createObject +import kotlinx.coroutines.runBlocking import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult @@ -127,7 +128,7 @@ private fun EventEntity.toTimelineEventEntity(roomMemberContentsByUser: HashMap< return timelineEventEntity } -internal suspend fun ThreadSummaryEntity.Companion.createOrUpdate( +internal fun ThreadSummaryEntity.Companion.createOrUpdate( threadSummaryType: ThreadSummaryUpdateType, realm: Realm, roomId: String, @@ -136,7 +137,8 @@ internal suspend fun ThreadSummaryEntity.Companion.createOrUpdate( roomMemberContentsByUser: HashMap<String, RoomMemberContent?>, roomEntity: RoomEntity, userId: String, - cryptoService: CryptoService? = null + cryptoService: CryptoService? = null, + currentTimeMillis: Long, ) { when (threadSummaryType) { ThreadSummaryUpdateType.REPLACE -> { @@ -152,11 +154,19 @@ internal suspend fun ThreadSummaryEntity.Companion.createOrUpdate( Timber.i("###THREADS ThreadSummaryHelper REPLACE eventId:${it.rootThreadEventId} ") } - val rootThreadEventEntity = createEventEntity(roomId, rootThreadEvent, realm).also { - decryptIfNeeded(cryptoService, it, roomId) + val rootThreadEventEntity = createEventEntity(realm, roomId, rootThreadEvent, currentTimeMillis).also { + try { + decryptIfNeeded(cryptoService, it, roomId) + } catch (e: InterruptedException) { + Timber.i("Decryption got interrupted") + } } - val latestThreadEventEntity = createLatestEventEntity(roomId, rootThreadEvent, roomMemberContentsByUser, realm)?.also { - decryptIfNeeded(cryptoService, it, roomId) + val latestThreadEventEntity = createLatestEventEntity(realm, roomId, rootThreadEvent, roomMemberContentsByUser, currentTimeMillis)?.also { + try { + decryptIfNeeded(cryptoService, it, roomId) + } catch (e: InterruptedException) { + Timber.i("Decryption got interrupted") + } } val isUserParticipating = rootThreadEvent.unsignedData.relations.latestThread.isUserParticipating == true || rootThreadEvent.senderId == userId roomMemberContentsByUser.addSenderState(realm, roomId, rootThreadEvent.senderId) @@ -204,14 +214,15 @@ internal suspend fun ThreadSummaryEntity.Companion.createOrUpdate( } } -private suspend fun decryptIfNeeded(cryptoService: CryptoService?, eventEntity: EventEntity, roomId: String) { +private fun decryptIfNeeded(cryptoService: CryptoService?, eventEntity: EventEntity, roomId: String) { cryptoService ?: return val event = eventEntity.asDomain() if (event.isEncrypted() && event.mxDecryptionResult == null && event.eventId != null) { try { Timber.i("###THREADS ThreadSummaryHelper request decryption for eventId:${event.eventId}") // Event from sync does not have roomId, so add it to the event first - val result = cryptoService.decryptEvent(event.copy(roomId = roomId), "") + // note: runBlocking should be used here while we are in realm single thread executor, to avoid thread switching + val result = runBlocking { cryptoService.decryptEvent(event.copy(roomId = roomId), "") } event.mxDecryptionResult = OlmDecryptionResult( payload = result.clearEvent, senderKey = result.senderCurve25519Key, @@ -258,8 +269,8 @@ private fun HashMap<String, RoomMemberContent?>.addSenderState(realm: Realm, roo /** * Create an EventEntity for the root thread event or get an existing one */ -private fun createEventEntity(roomId: String, event: Event, realm: Realm): EventEntity { - val ageLocalTs = event.unsignedData?.age?.let { System.currentTimeMillis() - it } +private fun createEventEntity(realm: Realm, roomId: String, event: Event, currentTimeMillis: Long): EventEntity { + val ageLocalTs = event.unsignedData?.age?.let { currentTimeMillis - it } return event.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION) } @@ -268,15 +279,17 @@ private fun createEventEntity(roomId: String, event: Event, realm: Realm): Event * state */ private fun createLatestEventEntity( + realm: Realm, roomId: String, rootThreadEvent: Event, roomMemberContentsByUser: HashMap<String, RoomMemberContent?>, - realm: Realm): EventEntity? { + currentTimeMillis: Long, +): EventEntity? { return getLatestEvent(rootThreadEvent)?.let { it.senderId?.let { senderId -> roomMemberContentsByUser.addSenderState(realm, roomId, senderId) } - createEventEntity(roomId, it, realm) + createEventEntity(realm, roomId, it, currentTimeMillis) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/TimelineEventEntityHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/TimelineEventEntityHelper.kt index ea508731b1f6200bebc6c784a552d0023be3da58..8a5d08cd30a7c073ae2f6a1b133a61d9e0bea21e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/TimelineEventEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/TimelineEventEntityHelper.kt @@ -19,9 +19,10 @@ package org.matrix.android.sdk.internal.database.helper import io.realm.Realm import org.matrix.android.sdk.internal.database.model.TimelineEventEntity import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields +import org.matrix.android.sdk.internal.database.query.where internal fun TimelineEventEntity.Companion.nextId(realm: Realm): Long { - val currentIdNum = realm.where(TimelineEventEntity::class.java).max(TimelineEventEntityFields.LOCAL_ID) + val currentIdNum = TimelineEventEntity.where(realm).max(TimelineEventEntityFields.LOCAL_ID) return if (currentIdNum == null) { 1 } else { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventAnnotationsSummaryMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventAnnotationsSummaryMapper.kt index 4a26b4c4bf940c94c7b9d25037cefc15d3d81899..c747ad334fee19ff858b40b69edfe901149b6236 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventAnnotationsSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventAnnotationsSummaryMapper.kt @@ -25,7 +25,6 @@ import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEnt internal object EventAnnotationsSummaryMapper { fun map(annotationsSummary: EventAnnotationsSummaryEntity): EventAnnotationsSummary { return EventAnnotationsSummary( - eventId = annotationsSummary.eventId, reactionsSummary = annotationsSummary.reactionsSummary.toList().map { ReactionAggregatedSummary( it.key, @@ -50,7 +49,6 @@ internal object EventAnnotationsSummaryMapper { }, referencesAggregatedSummary = annotationsSummary.referencesSummaryEntity?.let { ReferencesAggregatedSummary( - it.eventId, ContentMapper.map(it.content), it.sourceEvents.toList(), it.sourceLocalEcho.toList() @@ -58,8 +56,10 @@ internal object EventAnnotationsSummaryMapper { }, pollResponseSummary = annotationsSummary.pollResponseSummary?.let { PollResponseAggregatedSummaryEntityMapper.map(it) + }, + liveLocationShareAggregatedSummary = annotationsSummary.liveLocationShareAggregatedSummary?.let { + LiveLocationShareAggregatedSummaryMapper.map(it) } - ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventMapper.kt index 3083df062e622ce2599a1ef9f3b1ae8c08a7dc46..bc7d40bf6f1dcec8977063f41d4b92197d8ce9aa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventMapper.kt @@ -30,13 +30,14 @@ import org.matrix.android.sdk.api.session.threads.ThreadNotificationState import org.matrix.android.sdk.internal.database.model.EventEntity import org.matrix.android.sdk.internal.di.MoshiProvider import timber.log.Timber +import kotlin.random.Random internal object EventMapper { fun map(event: Event, roomId: String): EventEntity { val eventEntity = EventEntity() // TODO change this as we shouldn't use event everywhere - eventEntity.eventId = event.eventId ?: "$$roomId-${System.currentTimeMillis()}-${event.hashCode()}" + eventEntity.eventId = event.eventId ?: "$$roomId-${Random.nextLong()}-${event.hashCode()}" eventEntity.roomId = event.roomId ?: roomId eventEntity.content = ContentMapper.map(event.content) eventEntity.prevContent = ContentMapper.map(event.resolvedPrevContent()) @@ -126,7 +127,10 @@ internal fun EventEntity.asDomain(castJsonNumbers: Boolean = false): Event { return EventMapper.map(this, castJsonNumbers) } -internal fun Event.toEntity(roomId: String, sendState: SendState, ageLocalTs: Long?, contentToInject: String? = null): EventEntity { +internal fun Event.toEntity(roomId: String, + sendState: SendState, + ageLocalTs: Long?, + contentToInject: String? = null): EventEntity { return EventMapper.map(this, roomId).apply { this.sendState = sendState this.ageLocalTs = ageLocalTs diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt new file mode 100644 index 0000000000000000000000000000000000000000..71b36f88bd8f30a60f01c2e8655e094850a80de4 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/LiveLocationShareAggregatedSummaryMapper.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 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.internal.database.mapper + +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity + +internal object LiveLocationShareAggregatedSummaryMapper { + + fun map(entity: LiveLocationShareAggregatedSummaryEntity): LiveLocationShareAggregatedSummary { + return LiveLocationShareAggregatedSummary( + isActive = entity.isActive, + endOfLiveTimestampMillis = entity.endOfLiveTimestampMillis, + lastLocationDataContent = ContentMapper.map(entity.lastLocationContent).toModel<MessageBeaconLocationDataContent>() + ) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushConditionMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushConditionMapper.kt index 5c0a2ba9021ca6f5b120d240c309205a2f678daa..6521bf62d97cb792cf89335d3f7828b3044f9a79 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushConditionMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushConditionMapper.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.database.mapper -import org.matrix.android.sdk.api.pushrules.rest.PushCondition +import org.matrix.android.sdk.api.session.pushrules.rest.PushCondition import org.matrix.android.sdk.internal.database.model.PushConditionEntity internal object PushConditionMapper { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt index 12eff8efa1b1442a5d19b0865388f88d4c36b8a2..0b07754126277ea59eb78b7f45fbbaa721f79848 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt @@ -17,9 +17,9 @@ package org.matrix.android.sdk.internal.database.mapper import com.squareup.moshi.Types import io.realm.RealmList -import org.matrix.android.sdk.api.pushrules.Kind -import org.matrix.android.sdk.api.pushrules.rest.PushCondition -import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.Kind +import org.matrix.android.sdk.api.session.pushrules.rest.PushCondition +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule import org.matrix.android.sdk.internal.database.model.PushRuleEntity import org.matrix.android.sdk.internal.di.MoshiProvider import timber.log.Timber diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo019.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo019.kt index d63ef62889b71db469b79e3c2eb1b460b40afe31..754a66bb4b9de9059aa0fadc98e8c010a57acdd8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo019.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo019.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.util.Normalizer import org.matrix.android.sdk.internal.util.database.RealmMigrator internal class MigrateSessionTo019(realm: DynamicRealm, - private val normalizer: Normalizer) : RealmMigrator(realm, 19) { + private val normalizer: Normalizer) : RealmMigrator(realm, 19) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("RoomSummaryEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo027.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo027.kt new file mode 100644 index 0000000000000000000000000000000000000000..fdd8c46d027ae4b4f6654e6d5799df1d3c7e115e --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo027.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 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.internal.database.migration + +import io.realm.DynamicRealm +import io.realm.FieldAttribute +import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntityFields +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntityFields +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +/** + * Migrating to: + * Live location sharing aggregated summary + */ +internal class MigrateSessionTo027(realm: DynamicRealm) : RealmMigrator(realm, 27) { + + override fun doMigrate(realm: DynamicRealm) { + val liveLocationSummaryEntity = realm.schema.get("LiveLocationShareAggregatedSummaryEntity") + ?: realm.schema.create("LiveLocationShareAggregatedSummaryEntity") + .addField(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID, String::class.java, FieldAttribute.REQUIRED) + .addField(LiveLocationShareAggregatedSummaryEntityFields.ROOM_ID, String::class.java, FieldAttribute.REQUIRED) + .addField(LiveLocationShareAggregatedSummaryEntityFields.IS_ACTIVE, Boolean::class.java) + .setNullable(LiveLocationShareAggregatedSummaryEntityFields.IS_ACTIVE, true) + .addField(LiveLocationShareAggregatedSummaryEntityFields.END_OF_LIVE_TIMESTAMP_MILLIS, Long::class.java) + .setNullable(LiveLocationShareAggregatedSummaryEntityFields.END_OF_LIVE_TIMESTAMP_MILLIS, true) + .addField(LiveLocationShareAggregatedSummaryEntityFields.LAST_LOCATION_CONTENT, String::class.java) + ?: return + + realm.schema.get("EventAnnotationsSummaryEntity") + ?.addRealmObjectField(EventAnnotationsSummaryEntityFields.LIVE_LOCATION_SHARE_AGGREGATED_SUMMARY.`$`, liveLocationSummaryEntity) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo028.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo028.kt new file mode 100644 index 0000000000000000000000000000000000000000..1d0c638d7b8fc902a4ea192aebbb6dcc6b8e6b98 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo028.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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.internal.database.migration + +import io.realm.DynamicRealm +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntityFields +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +/** + * Migrating to: + * Live location sharing aggregated summary + */ +internal class MigrateSessionTo028(realm: DynamicRealm) : RealmMigrator(realm, 28) { + + override fun doMigrate(realm: DynamicRealm) { + realm.schema.get("LiveLocationShareAggregatedSummaryEntity") + ?.takeIf { !it.hasPrimaryKey() } + ?.addPrimaryKey(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/ChunkEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/ChunkEntity.kt index 88eb821aa9d9088a2241a30d0309cc30a3983dcf..822bc1bd8f45c9e5f0326a61371b2e073af4354d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/ChunkEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/ChunkEntity.kt @@ -24,19 +24,20 @@ import io.realm.annotations.LinkingObjects import org.matrix.android.sdk.internal.extensions.assertIsManaged import org.matrix.android.sdk.internal.extensions.clearWith -internal open class ChunkEntity(@Index var prevToken: String? = null, +internal open class ChunkEntity( + @Index var prevToken: String? = null, // Because of gaps we can have several chunks with nextToken == null - @Index var nextToken: String? = null, - var prevChunk: ChunkEntity? = null, - var nextChunk: ChunkEntity? = null, - var stateEvents: RealmList<EventEntity> = RealmList(), - var timelineEvents: RealmList<TimelineEventEntity> = RealmList(), + @Index var nextToken: String? = null, + var prevChunk: ChunkEntity? = null, + var nextChunk: ChunkEntity? = null, + var stateEvents: RealmList<EventEntity> = RealmList(), + var timelineEvents: RealmList<TimelineEventEntity> = RealmList(), // Only one chunk will have isLastForward == true - @Index var isLastForward: Boolean = false, - @Index var isLastBackward: Boolean = false, + @Index var isLastForward: Boolean = false, + @Index var isLastBackward: Boolean = false, // Threads - @Index var rootThreadEventId: String? = null, - @Index var isLastForwardThread: Boolean = false, + @Index var rootThreadEventId: String? = null, + @Index var isLastForwardThread: Boolean = false, ) : RealmObject() { fun identifier() = "${prevToken}_$nextToken" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventAnnotationsSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventAnnotationsSummaryEntity.kt index 3e8813042004e6fd9c31c33449b185b2923e2d50..c3abd8b028b92a211607f5bb116cd15332835c16 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventAnnotationsSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventAnnotationsSummaryEntity.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.database.model import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.PrimaryKey +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity import timber.log.Timber internal open class EventAnnotationsSummaryEntity( @@ -27,7 +28,8 @@ internal open class EventAnnotationsSummaryEntity( var reactionsSummary: RealmList<ReactionAggregatedSummaryEntity> = RealmList(), var editSummary: EditAggregatedSummaryEntity? = null, var referencesSummaryEntity: ReferencesAggregatedSummaryEntity? = null, - var pollResponseSummary: PollResponseAggregatedSummaryEntity? = null + var pollResponseSummary: PollResponseAggregatedSummaryEntity? = null, + var liveLocationShareAggregatedSummary: LiveLocationShareAggregatedSummaryEntity? = null, ) : RealmObject() { /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupEntity.kt index 527f782359022ab2fb29e42b5a8d0984e055a00d..0120bb91d3ef2edcd5a8ee49b093aed01fb94234 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/GroupEntity.kt @@ -25,7 +25,7 @@ import org.matrix.android.sdk.api.session.room.model.Membership * Then GetGroupDataTask is called regularly to fetch group information from the homeserver. */ internal open class GroupEntity(@PrimaryKey var groupId: String = "") : - RealmObject() { + RealmObject() { private var membershipStr: String = Membership.NONE.name var membership: Membership diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PushRulesEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PushRulesEntity.kt index 4125d90891233ac99948f3a8ce9d1c0ffe49d25b..62bf40c1d2e9d9eb846cd8896db644841e3309e1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PushRulesEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PushRulesEntity.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.database.model import io.realm.RealmList import io.realm.RealmObject -import org.matrix.android.sdk.api.pushrules.RuleKind +import org.matrix.android.sdk.api.session.pushrules.RuleKind import org.matrix.android.sdk.internal.extensions.clearWith internal open class PushRulesEntity( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomEntity.kt index 4a6f6a7bf8970a893e6f018431db61ee57a0a7ee..d8e6b8af0faaa0fcc22562b10ec993bb6f01903c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomEntity.kt @@ -48,8 +48,10 @@ internal open class RoomEntity(@PrimaryKey var roomId: String = "", set(value) { membersLoadStatusStr = value.name } + companion object } + internal fun RoomEntity.removeThreadSummaryIfNeeded(eventId: String) { assertIsManaged() threadSummaries.findRootOrLatest(eventId)?.let { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt index d0d23dd491b3336676cd4561a184cf8d5655c17e..9a92b145101f0da1adf7a83c37447dea783b8c64 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.database.model import io.realm.annotations.RealmModule +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntity import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntity @@ -47,6 +48,7 @@ import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntit EditAggregatedSummaryEntity::class, EditionOfEvent::class, PollResponseAggregatedSummaryEntity::class, + LiveLocationShareAggregatedSummaryEntity::class, ReferencesAggregatedSummaryEntity::class, PushRulesEntity::class, PushRuleEntity::class, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/TimelineEventEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/TimelineEventEntity.kt index aacd6570bc4768ed37c7ea26e292b3f3e3051cef..477c04fe518097b6aef604a9214b09ab52337cf8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/TimelineEventEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/TimelineEventEntity.kt @@ -32,8 +32,8 @@ internal open class TimelineEventEntity(var localId: Long = 0, var isUniqueDisplayName: Boolean = false, var senderAvatar: String? = null, var senderMembershipEventId: String? = null, - // ownedByThreadChunk indicates that the current TimelineEventEntity belongs - // to a thread chunk and is a temporarily event. + // ownedByThreadChunk indicates that the current TimelineEventEntity belongs + // to a thread chunk and is a temporarily event. var ownedByThreadChunk: Boolean = false, var readReceipts: ReadReceiptsSummaryEntity? = null ) : RealmObject() { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt new file mode 100644 index 0000000000000000000000000000000000000000..1376839f9375d0ce7ee5c1507e552492d4fd07f6 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/livelocation/LiveLocationShareAggregatedSummaryEntity.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 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.internal.database.model.livelocation + +import io.realm.RealmObject +import io.realm.annotations.PrimaryKey + +/** + * Aggregation info concerning a live location share. + */ +internal open class LiveLocationShareAggregatedSummaryEntity( + /** + * Event id of the event that started the live. + */ + @PrimaryKey + var eventId: String = "", + + var roomId: String = "", + + var isActive: Boolean? = null, + + var endOfLiveTimestampMillis: Long? = null, + + /** + * For now we persist this as a JSON for greater flexibility + * @see [org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent] + */ + var lastLocationContent: String? = null, +) : RealmObject() { + companion object +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt index a33ba82f7aa000df11165e3c028b5273c48fa97f..9350102137042b6b35c6e94762143f9c07da0914 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt @@ -56,18 +56,21 @@ internal fun ChunkEntity.Companion.findLastForwardChunkOfRoom(realm: Realm, room .equalTo(ChunkEntityFields.IS_LAST_FORWARD, true) .findFirst() } + internal fun ChunkEntity.Companion.findLastForwardChunkOfThread(realm: Realm, roomId: String, rootThreadEventId: String): ChunkEntity? { return where(realm, roomId) .equalTo(ChunkEntityFields.ROOT_THREAD_EVENT_ID, rootThreadEventId) .equalTo(ChunkEntityFields.IS_LAST_FORWARD_THREAD, true) .findFirst() } + internal fun ChunkEntity.Companion.findEventInThreadChunk(realm: Realm, roomId: String, event: String): ChunkEntity? { return where(realm, roomId) .`in`(ChunkEntityFields.TIMELINE_EVENTS.EVENT_ID, arrayListOf(event).toTypedArray()) .equalTo(ChunkEntityFields.IS_LAST_FORWARD_THREAD, true) .findFirst() } + internal fun ChunkEntity.Companion.findAllIncludingEvents(realm: Realm, eventIds: List<String>): RealmResults<ChunkEntity> { return realm.where<ChunkEntity>() .`in`(ChunkEntityFields.TIMELINE_EVENTS.EVENT_ID, eventIds.toTypedArray()) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt new file mode 100644 index 0000000000000000000000000000000000000000..2e2e939fa2003e29e12902e1255eedb591723928 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LiveLocationShareAggregatedSummaryEntityQuery.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 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.internal.database.query + +import io.realm.Realm +import io.realm.RealmQuery +import io.realm.kotlin.where +import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntity +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntityFields + +internal fun LiveLocationShareAggregatedSummaryEntity.Companion.where( + realm: Realm, + roomId: String, + eventId: String, +): RealmQuery<LiveLocationShareAggregatedSummaryEntity> { + return realm.where<LiveLocationShareAggregatedSummaryEntity>() + .equalTo(LiveLocationShareAggregatedSummaryEntityFields.ROOM_ID, roomId) + .equalTo(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID, eventId) +} + +internal fun LiveLocationShareAggregatedSummaryEntity.Companion.create( + realm: Realm, + roomId: String, + eventId: String, +): LiveLocationShareAggregatedSummaryEntity { + val obj = realm.createObject(LiveLocationShareAggregatedSummaryEntity::class.java, eventId).apply { + this.roomId = roomId + } + val annotationSummary = EventAnnotationsSummaryEntity.getOrCreate(realm, roomId = roomId, eventId = eventId) + annotationSummary.liveLocationShareAggregatedSummary = obj + + return obj +} + +internal fun LiveLocationShareAggregatedSummaryEntity.Companion.getOrCreate( + realm: Realm, + roomId: String, + eventId: String, +): LiveLocationShareAggregatedSummaryEntity { + return LiveLocationShareAggregatedSummaryEntity.where(realm, roomId, eventId).findFirst() + ?: LiveLocationShareAggregatedSummaryEntity.create(realm, roomId, eventId) +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/PushersQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/PushersQueries.kt index 1f6b210252a10d5d30a0d1d042ac0c549a4affe5..3cea19a690f8d87e13bafb6a4b67b4c8d3559606 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/PushersQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/PushersQueries.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.database.query import io.realm.Realm import io.realm.RealmQuery import io.realm.kotlin.where -import org.matrix.android.sdk.api.pushrules.RuleKind +import org.matrix.android.sdk.api.session.pushrules.RuleKind import org.matrix.android.sdk.internal.database.model.PushRuleEntity import org.matrix.android.sdk.internal.database.model.PushRuleEntityFields import org.matrix.android.sdk.internal.database.model.PushRulesEntity diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ThreadSummaryEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ThreadSummaryEntityQueries.kt index 517d43d7cf965efe4593be5144d3028e45a2ddfe..eab27404330f875aecc30af47f67b834cfd2e61a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ThreadSummaryEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ThreadSummaryEntityQueries.kt @@ -39,9 +39,11 @@ internal fun ThreadSummaryEntity.Companion.getOrCreate(realm: Realm, roomId: Str this.rootThreadEventId = rootThreadEventId } } + internal fun ThreadSummaryEntity.Companion.getOrNull(realm: Realm, roomId: String, rootThreadEventId: String): ThreadSummaryEntity? { return where(realm, roomId, rootThreadEventId).findFirst() } + internal fun RealmList<ThreadSummaryEntity>.find(rootThreadEventId: String): ThreadSummaryEntity? { return this.where() .equalTo(ThreadSummaryEntityFields.ROOT_THREAD_EVENT_ID, rootThreadEventId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventEntityQueries.kt index 81d5ac835f1465b7249a786ab224a3e409eab6cd..215ab34f95438a7c697f5b7f48274e4e4920bdb0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/TimelineEventEntityQueries.kt @@ -29,26 +29,35 @@ import org.matrix.android.sdk.internal.database.model.RoomEntity import org.matrix.android.sdk.internal.database.model.TimelineEventEntity import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields -internal fun TimelineEventEntity.Companion.where(realm: Realm, roomId: String, eventId: String): RealmQuery<TimelineEventEntity> { - return realm.where<TimelineEventEntity>() +internal fun TimelineEventEntity.Companion.where(realm: Realm): RealmQuery<TimelineEventEntity> { + return realm.where() +} + +internal fun TimelineEventEntity.Companion.where(realm: Realm, + roomId: String, + eventId: String): RealmQuery<TimelineEventEntity> { + return where(realm) .equalTo(TimelineEventEntityFields.ROOM_ID, roomId) .equalTo(TimelineEventEntityFields.EVENT_ID, eventId) } -internal fun TimelineEventEntity.Companion.where(realm: Realm, roomId: String, eventIds: List<String>): RealmQuery<TimelineEventEntity> { - return realm.where<TimelineEventEntity>() +internal fun TimelineEventEntity.Companion.where(realm: Realm, + roomId: String, + eventIds: List<String>): RealmQuery<TimelineEventEntity> { + return where(realm) .equalTo(TimelineEventEntityFields.ROOM_ID, roomId) .`in`(TimelineEventEntityFields.EVENT_ID, eventIds.toTypedArray()) } internal fun TimelineEventEntity.Companion.whereRoomId(realm: Realm, roomId: String): RealmQuery<TimelineEventEntity> { - return realm.where<TimelineEventEntity>() + return where(realm) .equalTo(TimelineEventEntityFields.ROOM_ID, roomId) } -internal fun TimelineEventEntity.Companion.findWithSenderMembershipEvent(realm: Realm, senderMembershipEventId: String): List<TimelineEventEntity> { - return realm.where<TimelineEventEntity>() +internal fun TimelineEventEntity.Companion.findWithSenderMembershipEvent(realm: Realm, + senderMembershipEventId: String): List<TimelineEventEntity> { + return where(realm) .equalTo(TimelineEventEntityFields.SENDER_MEMBERSHIP_EVENT_ID, senderMembershipEventId) .findAll() } @@ -110,12 +119,12 @@ internal fun RealmQuery<TimelineEventEntity>.filterTypes(filterTypes: List<Strin return if (filterTypes.isEmpty()) { this } else { - this.`in`(TimelineEventEntityFields.ROOT.TYPE, filterTypes.toTypedArray()) + `in`(TimelineEventEntityFields.ROOT.TYPE, filterTypes.toTypedArray()) } } internal fun RealmList<TimelineEventEntity>.find(eventId: String): TimelineEventEntity? { - return this.where() + return where() .equalTo(TimelineEventEntityFields.EVENT_ID, eventId) .findFirst() } @@ -132,3 +141,14 @@ internal fun RealmQuery<TimelineEventEntity>.filterSendStates(sendStates: List<S val sendStatesStr = sendStates.map { it.name }.toTypedArray() return `in`(TimelineEventEntityFields.ROOT.SEND_STATE_STR, sendStatesStr) } + +/** + * Find all TimelineEventEntity items where sender is in senderIds collection, excluding state events + */ +internal fun TimelineEventEntity.Companion.findAllFrom(realm: Realm, + senderIds: Collection<String>): RealmResults<TimelineEventEntity> { + return where(realm) + .`in`(TimelineEventEntityFields.ROOT.SENDER, senderIds.toTypedArray()) + .isNull(TimelineEventEntityFields.ROOT.STATE_KEY) + .findAll() +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt index cd7c99b8f964e6adff32c5fb242f5d91abd83a30..3d2b2bfbfb8c19f7e4cad09f8b2949c2eaaad3af 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt @@ -44,7 +44,7 @@ internal interface NetworkConnectivityChecker { internal class DefaultNetworkConnectivityChecker @Inject constructor(private val homeServerPinger: HomeServerPinger, private val backgroundDetectionObserver: BackgroundDetectionObserver, private val networkCallbackStrategy: NetworkCallbackStrategy) : - NetworkConnectivityChecker { + NetworkConnectivityChecker { private val hasInternetAccess = AtomicBoolean(true) private val listeners = Collections.synchronizedSet(LinkedHashSet<NetworkConnectivityChecker.Listener>()) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RequestExecutor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RequestExecutor.kt index 5cd2d880003ba2caf9d6f956b11d60c587e58e7e..71df7c08be9c63607e1d622619bbaf857f70410d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RequestExecutor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RequestExecutor.kt @@ -15,6 +15,7 @@ */ package org.matrix.android.sdk.internal.network + import org.matrix.android.sdk.internal.network.executeRequest as internalExecuteRequest internal interface RequestExecutor { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt index ac097f57ee604159f9b6447ade65fa6aae2b3d47..78f1c84f3dd417d99cc4c5620581fda8bc46476b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt @@ -38,6 +38,7 @@ import org.matrix.android.sdk.internal.di.SessionDownloadsDirectory import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificateWithProgress import org.matrix.android.sdk.internal.session.download.DownloadProgressInterceptor.Companion.DOWNLOAD_PROGRESS_INTERCEPTOR_HEADER import org.matrix.android.sdk.internal.util.file.AtomicFileCreator +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.android.sdk.internal.util.writeToFile import timber.log.Timber import java.io.File @@ -51,7 +52,8 @@ internal class DefaultFileService @Inject constructor( private val contentUrlResolver: ContentUrlResolver, @UnauthenticatedWithCertificateWithProgress private val okHttpClient: OkHttpClient, - private val coroutineDispatchers: MatrixCoroutineDispatchers + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val clock: Clock, ) : FileService { // Legacy folder, will be deleted @@ -123,7 +125,7 @@ internal class DefaultFileService @Inject constructor( val resolvedUrl = contentUrlResolver.resolveForDownload(url, elementToDecrypt) ?: throw IllegalArgumentException("url is null") val request = when (resolvedUrl) { - is ContentUrlResolver.ResolvedMethod.GET -> { + is ContentUrlResolver.ResolvedMethod.GET -> { Request.Builder() .url(resolvedUrl.url) .header(DOWNLOAD_PROGRESS_INTERCEPTOR_HEADER, url) @@ -182,7 +184,8 @@ internal class DefaultFileService @Inject constructor( MXEncryptedAttachments.decryptAttachment( inputStream, elementToDecrypt, - outputStream + outputStream, + clock ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt index 1e533158a76d2454996e0d4574265ffc2710a4ba..5f77cfb23a702ec54ab3cdb615897e5b899eb4fa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt @@ -26,7 +26,6 @@ import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.auth.data.SessionParams import org.matrix.android.sdk.api.failure.GlobalError import org.matrix.android.sdk.api.federation.FederationService -import org.matrix.android.sdk.api.pushrules.PushRuleService import org.matrix.android.sdk.api.session.EventStreamService import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.SessionLifecycleObserver @@ -53,6 +52,7 @@ import org.matrix.android.sdk.api.session.permalinks.PermalinkService import org.matrix.android.sdk.api.session.presence.PresenceService import org.matrix.android.sdk.api.session.profile.ProfileService import org.matrix.android.sdk.api.session.pushers.PushersService +import org.matrix.android.sdk.api.session.pushrules.PushRuleService import org.matrix.android.sdk.api.session.room.RoomDirectoryService import org.matrix.android.sdk.api.session.room.RoomService import org.matrix.android.sdk.api.session.search.SearchService @@ -124,12 +124,12 @@ internal class DefaultSession @Inject constructor( private val syncStatusService: Lazy<SyncStatusService>, private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>, private val accountDataService: Lazy<SessionAccountDataService>, - private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>, + private val sharedSecretStorageService: Lazy<SharedSecretStorageService>, private val accountService: Lazy<AccountService>, private val eventService: Lazy<EventService>, private val contentScannerService: Lazy<ContentScannerService>, - private val identityService: IdentityService, - private val integrationManagerService: IntegrationManagerService, + private val identityService: Lazy<IdentityService>, + private val integrationManagerService: Lazy<IntegrationManagerService>, private val thirdPartyService: Lazy<ThirdPartyService>, private val callSignalingService: Lazy<CallSignalingService>, private val spaceService: Lazy<SpaceService>, @@ -140,28 +140,7 @@ internal class DefaultSession @Inject constructor( @UnauthenticatedWithCertificate private val unauthenticatedWithCertificateOkHttpClient: Lazy<OkHttpClient> ) : Session, - GlobalErrorHandler.Listener, - RoomService by roomService.get(), - RoomDirectoryService by roomDirectoryService.get(), - GroupService by groupService.get(), - UserService by userService.get(), - SignOutService by signOutService.get(), - FilterService by filterService.get(), - PushRuleService by pushRuleService.get(), - PushersService by pushersService.get(), - EventService by eventService.get(), - TermsService by termsService.get(), - SyncStatusService by syncStatusService.get(), - SecureStorageService by secureStorageService.get(), - HomeServerCapabilitiesService by homeServerCapabilitiesService.get(), - ProfileService by profileService.get(), - PresenceService by presenceService.get(), - AccountService by accountService.get(), - ToDeviceService by toDeviceService.get(), - EventStreamService by eventStreamService.get() { - - override val sharedSecretStorageService: SharedSecretStorageService - get() = _sharedSecretStorageService.get() + GlobalErrorHandler.Listener { private var isOpen = false @@ -274,42 +253,44 @@ internal class DefaultSession @Inject constructor( } override fun contentUrlResolver() = contentUrlResolver - override fun contentUploadProgressTracker() = contentUploadProgressTracker - override fun typingUsersTracker() = typingUsersTracker - override fun contentDownloadProgressTracker(): ContentDownloadStateTracker = contentDownloadStateTracker override fun cryptoService(): CryptoService = cryptoService.get() - override fun contentScannerService(): ContentScannerService = contentScannerService.get() - - override fun identityService() = identityService - + override fun identityService(): IdentityService = identityService.get() + override fun homeServerCapabilitiesService(): HomeServerCapabilitiesService = homeServerCapabilitiesService.get() + override fun roomService(): RoomService = roomService.get() + override fun roomDirectoryService(): RoomDirectoryService = roomDirectoryService.get() + override fun groupService(): GroupService = groupService.get() + override fun userService(): UserService = userService.get() + override fun signOutService(): SignOutService = signOutService.get() + override fun filterService(): FilterService = filterService.get() + override fun pushRuleService(): PushRuleService = pushRuleService.get() + override fun pushersService(): PushersService = pushersService.get() + override fun eventService(): EventService = eventService.get() + override fun termsService(): TermsService = termsService.get() + override fun syncStatusService(): SyncStatusService = syncStatusService.get() + override fun secureStorageService(): SecureStorageService = secureStorageService.get() + override fun profileService(): ProfileService = profileService.get() + override fun presenceService(): PresenceService = presenceService.get() + override fun accountService(): AccountService = accountService.get() + override fun toDeviceService(): ToDeviceService = toDeviceService.get() + override fun eventStreamService(): EventStreamService = eventStreamService.get() override fun fileService(): FileService = defaultFileService.get() - override fun permalinkService(): PermalinkService = permalinkService.get() - override fun widgetService(): WidgetService = widgetService.get() - override fun mediaService(): MediaService = mediaService.get() - - override fun integrationManagerService() = integrationManagerService - + override fun integrationManagerService(): IntegrationManagerService = integrationManagerService.get() override fun callSignalingService(): CallSignalingService = callSignalingService.get() - override fun searchService(): SearchService = searchService.get() - override fun federationService(): FederationService = federationService.get() - override fun thirdPartyService(): ThirdPartyService = thirdPartyService.get() - override fun spaceService(): SpaceService = spaceService.get() - override fun openIdService(): OpenIdService = openIdService.get() - override fun accountDataService(): SessionAccountDataService = accountDataService.get() + override fun sharedSecretStorageService(): SharedSecretStorageService = sharedSecretStorageService.get() override fun getOkHttpClient(): OkHttpClient { return unauthenticatedWithCertificateOkHttpClient.get() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DeactivateAccountTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DeactivateAccountTask.kt index 752856b931aac41d6e16e5d08e2b6098bb1cba47..9f3f1f649eea158658c51d6fa3f2e74cb60a2553 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DeactivateAccountTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DeactivateAccountTask.kt @@ -18,6 +18,8 @@ package org.matrix.android.sdk.internal.session.account import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor +import org.matrix.android.sdk.api.session.uia.UiaResult +import org.matrix.android.sdk.api.session.uia.exceptions.UiaCancelledException import org.matrix.android.sdk.internal.auth.registration.handleUIA import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest @@ -51,18 +53,24 @@ internal class DefaultDeactivateAccountTask @Inject constructor( } true } catch (throwable: Throwable) { - if (!handleUIA( - failure = throwable, - interceptor = params.userInteractiveAuthInterceptor, - retryBlock = { authUpdate -> - execute(params.copy(userAuthParam = authUpdate)) - } - ) - ) { - Timber.d("## UIA: propagate failure") - throw throwable - } else { - false + when (handleUIA( + failure = throwable, + interceptor = params.userInteractiveAuthInterceptor, + retryBlock = { authUpdate -> + execute(params.copy(userAuthParam = authUpdate)) + } + )) { + UiaResult.SUCCESS -> { + false + } + UiaResult.FAILURE -> { + Timber.d("## UIA: propagate failure") + throw throwable + } + UiaResult.CANCELLED -> { + Timber.d("## UIA: cancelled") + throw UiaCancelledException() + } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/CallEventProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/CallEventProcessor.kt index 3f199c5cce951ab274d31556b346f0c159717af3..b15a6474218db146a2204478e08fc00746000b1d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/CallEventProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/CallEventProcessor.kt @@ -30,7 +30,7 @@ private val loggerTag = LoggerTag("CallEventProcessor", LoggerTag.VOIP) @SessionScope internal class CallEventProcessor @Inject constructor(private val callSignalingHandler: CallSignalingHandler) : - EventInsertLiveProcessor { + EventInsertLiveProcessor { private val allowedTypes = listOf( EventType.CALL_ANSWER, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/CallSignalingHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/CallSignalingHandler.kt index 59058bf9767648cea08f3dea30bbfb7bfca60502..c4f711a9e6fb33966a55e93bfde2b4c59b4a80eb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/CallSignalingHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/CallSignalingHandler.kt @@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.session.room.model.call.CallSelectAnswerConten import org.matrix.android.sdk.api.session.room.model.call.CallSignalingContent import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject @@ -41,9 +42,12 @@ private val loggerTag = LoggerTag("CallSignalingHandler", LoggerTag.VOIP) private const val MAX_AGE_TO_RING = 40_000 @SessionScope -internal class CallSignalingHandler @Inject constructor(private val activeCallHandler: ActiveCallHandler, - private val mxCallFactory: MxCallFactory, - @UserId private val userId: String) { +internal class CallSignalingHandler @Inject constructor( + private val activeCallHandler: ActiveCallHandler, + private val mxCallFactory: MxCallFactory, + @UserId private val userId: String, + private val clock: Clock, +) { private val invitedCallIds = mutableSetOf<String>() private val callListeners = mutableSetOf<CallListener>() @@ -184,7 +188,7 @@ internal class CallSignalingHandler @Inject constructor(private val activeCallHa if (event.roomId == null || event.senderId == null) { return } - val now = System.currentTimeMillis() + val now = clock.epochMillis() val age = now - (event.ageLocalTs ?: now) if (age > MAX_AGE_TO_RING) { Timber.tag(loggerTag.value).w("Call invite is too old to ring.") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/MxCallFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/MxCallFactory.kt index 547be2253f80d60c28d613c41be91872a4565f68..9ec892b65db549942596b9b0d6e3f5068d0609e4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/MxCallFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/MxCallFactory.kt @@ -28,6 +28,7 @@ import org.matrix.android.sdk.internal.session.call.model.MxCallImpl import org.matrix.android.sdk.internal.session.profile.GetProfileInfoTask import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor +import org.matrix.android.sdk.internal.util.time.Clock import javax.inject.Inject internal class MxCallFactory @Inject constructor( @@ -36,7 +37,8 @@ internal class MxCallFactory @Inject constructor( private val eventSenderProcessor: EventSenderProcessor, private val matrixConfiguration: MatrixConfiguration, private val getProfileInfoTask: GetProfileInfoTask, - @UserId private val userId: String + @UserId private val userId: String, + private val clock: Clock, ) { fun createIncomingCall(roomId: String, opponentUserId: String, content: CallInviteContent): MxCall? { @@ -51,7 +53,8 @@ internal class MxCallFactory @Inject constructor( localEchoEventFactory = localEchoEventFactory, eventSenderProcessor = eventSenderProcessor, matrixConfiguration = matrixConfiguration, - getProfileInfoTask = getProfileInfoTask + getProfileInfoTask = getProfileInfoTask, + clock = clock, ).apply { updateOpponentData(opponentUserId, content, content.capabilities) } @@ -68,7 +71,8 @@ internal class MxCallFactory @Inject constructor( localEchoEventFactory = localEchoEventFactory, eventSenderProcessor = eventSenderProcessor, matrixConfiguration = matrixConfiguration, - getProfileInfoTask = getProfileInfoTask + getProfileInfoTask = getProfileInfoTask, + clock = clock, ).apply { // Setup with this userId, might be updated when processing the Answer event this.opponentUserId = opponentUserId diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/model/MxCallImpl.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/model/MxCallImpl.kt index a89713870a7513bd4eabffb530bd0efe71ae677b..796e83311f89bde906a7c58eea9ca0112f1445cd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/model/MxCallImpl.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/model/MxCallImpl.kt @@ -46,6 +46,7 @@ import org.matrix.android.sdk.internal.session.call.DefaultCallSignalingService import org.matrix.android.sdk.internal.session.profile.GetProfileInfoTask import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import java.math.BigDecimal @@ -61,7 +62,8 @@ internal class MxCallImpl( private val localEchoEventFactory: LocalEchoEventFactory, private val eventSenderProcessor: EventSenderProcessor, private val matrixConfiguration: MatrixConfiguration, - private val getProfileInfoTask: GetProfileInfoTask + private val getProfileInfoTask: GetProfileInfoTask, + private val clock: Clock, ) : MxCall { override var opponentPartyId: Optional<String>? = null @@ -250,7 +252,7 @@ internal class MxCallImpl( private fun createEventAndLocalEcho(localId: String = LocalEcho.createLocalEchoId(), type: String, roomId: String, content: Content): Event { return Event( roomId = roomId, - originServerTs = System.currentTimeMillis(), + originServerTs = clock.epochMillis(), senderId = userId, eventId = localId, type = type, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt index e9cb4238933d26d429b12ca51a820cde5a557fad..f96a019fe22aabfeaeae39b8b9401d44d46152e9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt @@ -148,8 +148,8 @@ internal class FileUploader @Inject constructor( .post(requestBody) .build() - return withContext(coroutineDispatchers.io) { - okHttpClient.newCall(request).awaitResponse().use { response -> + return withContext(coroutineDispatchers.io) { + okHttpClient.newCall(request).awaitResponse().use { response -> if (!response.isSuccessful) { throw response.toFailure(globalErrorReceiver) } else { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt index 01eb52ff2270e875444f6ae7c4e18c583c6a4fbc..c5aa6cd5e717bc1864d32cbaf1f463161ccb8545 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt @@ -68,16 +68,16 @@ internal class ImageCompressor @Inject constructor( val orientation = exifInfo.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) val matrix = Matrix() when (orientation) { - ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270f) - ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180f) - ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90f) + ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270f) + ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180f) + ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90f) ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> matrix.preScale(-1f, 1f) - ExifInterface.ORIENTATION_FLIP_VERTICAL -> matrix.preScale(1f, -1f) - ExifInterface.ORIENTATION_TRANSPOSE -> { + ExifInterface.ORIENTATION_FLIP_VERTICAL -> matrix.preScale(1f, -1f) + ExifInterface.ORIENTATION_TRANSPOSE -> { matrix.preRotate(-90f) matrix.preScale(-1f, 1f) } - ExifInterface.ORIENTATION_TRANSVERSE -> { + ExifInterface.ORIENTATION_TRANSVERSE -> { matrix.preRotate(90f) matrix.preScale(-1f, 1f) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt index 75606f2e7a7cb407122db257cd6e95af70d50a33..75a79abcdbcd2aad7e828ebfe9b0ceb8de796da1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt @@ -46,6 +46,7 @@ import org.matrix.android.sdk.internal.session.room.send.LocalEchoIdentifiers import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository import org.matrix.android.sdk.internal.session.room.send.MultipleEventSendingDispatcherWorker import org.matrix.android.sdk.internal.util.TemporaryFileCreator +import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.android.sdk.internal.util.toMatrixErrorStr import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker import org.matrix.android.sdk.internal.worker.SessionWorkerParams @@ -87,6 +88,7 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter @Inject lateinit var thumbnailExtractor: ThumbnailExtractor @Inject lateinit var localEchoRepository: LocalEchoRepository @Inject lateinit var temporaryFileCreator: TemporaryFileCreator + @Inject lateinit var clock: Clock override fun injectWith(injector: SessionComponent) { injector.inject(this) @@ -243,7 +245,7 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter .also { filesToDelete.add(it) } uploadedFileEncryptedFileInfo = - MXEncryptedAttachments.encrypt(fileToUpload.inputStream(), encryptedFile) { read, total -> + MXEncryptedAttachments.encrypt(fileToUpload.inputStream(), encryptedFile, clock) { read, total -> notifyTracker(params) { contentUploadStateTracker.setEncrypting(it, read.toLong(), total.toLong()) } @@ -329,7 +331,7 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter if (params.isEncrypted) { Timber.v("Encrypt thumbnail") notifyTracker(params) { contentUploadStateTracker.setEncryptingThumbnail(it) } - val encryptionResult = MXEncryptedAttachments.encryptAttachment(thumbnailData.bytes.inputStream()) + val encryptionResult = MXEncryptedAttachments.encryptAttachment(thumbnailData.bytes.inputStream(), clock) val contentUploadResponse = fileUploader.uploadByteArray( byteArray = encryptionResult.encryptedByteArray, filename = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DefaultContentScannerService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DefaultContentScannerService.kt index da7e2d102e081ca99399cecbc38a855f54c342ed..5aaf0587571d48c800bcbf8b16344dd75f93caef 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DefaultContentScannerService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DefaultContentScannerService.kt @@ -33,6 +33,7 @@ import org.matrix.android.sdk.internal.session.contentscanner.tasks.GetServerPub import org.matrix.android.sdk.internal.session.contentscanner.tasks.ScanEncryptedTask import org.matrix.android.sdk.internal.session.contentscanner.tasks.ScanMediaTask import org.matrix.android.sdk.internal.task.TaskExecutor +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject @@ -46,7 +47,8 @@ internal class DefaultContentScannerService @Inject constructor( private val getServerPublicKeyTask: GetServerPublicKeyTask, private val scanEncryptedTask: ScanEncryptedTask, private val scanMediaTask: ScanMediaTask, - private val taskExecutor: TaskExecutor + private val taskExecutor: TaskExecutor, + private val clock: Clock, ) : ContentScannerService { // Cache public key in memory @@ -71,11 +73,13 @@ internal class DefaultContentScannerService @Inject constructor( override suspend fun getScanResultForAttachment(mxcUrl: String, fileInfo: ElementToDecrypt?): ScanStatusInfo { val result = if (fileInfo != null) { - scanEncryptedTask.execute(ScanEncryptedTask.Params( - mxcUrl = mxcUrl, - publicServerKey = getServerPublicKey(false), - encryptedInfo = fileInfo - )) + scanEncryptedTask.execute( + ScanEncryptedTask.Params( + mxcUrl = mxcUrl, + publicServerKey = getServerPublicKey(false), + encryptedInfo = fileInfo + ) + ) } else { scanMediaTask.execute(ScanMediaTask.Params(mxcUrl)) } @@ -83,7 +87,7 @@ internal class DefaultContentScannerService @Inject constructor( return ScanStatusInfo( state = if (result.clean) ScanState.TRUSTED else ScanState.INFECTED, humanReadableMessage = result.info, - scanDateTimestamp = System.currentTimeMillis() + scanDateTimestamp = clock.epochMillis() ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/ContentScannerEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/ContentScannerEntityQueries.kt index b47be235c602506f5313168d53d2628ca3e0fdac..e4b64a1a0e5442183d9183c7cb7cf74af40c4629 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/ContentScannerEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/ContentScannerEntityQueries.kt @@ -31,11 +31,14 @@ internal fun ContentScanResultEntity.Companion.get(realm: Realm, attachmentUrl: .findFirst() } -internal fun ContentScanResultEntity.Companion.getOrCreate(realm: Realm, attachmentUrl: String, contentScannerUrl: String?): ContentScanResultEntity { +internal fun ContentScanResultEntity.Companion.getOrCreate(realm: Realm, + attachmentUrl: String, + contentScannerUrl: String?, + currentTimeMillis: Long): ContentScanResultEntity { return ContentScanResultEntity.get(realm, attachmentUrl, contentScannerUrl) ?: realm.createObject<ContentScanResultEntity>().also { it.mediaUrl = attachmentUrl - it.scanDateTimestamp = System.currentTimeMillis() + it.scanDateTimestamp = currentTimeMillis it.scannerUrl = contentScannerUrl } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/RealmContentScannerStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/RealmContentScannerStore.kt index 947a66c8b9782f609c5aecefef53985b0f750b12..27729d38c78679eeba49c8ea3ae9389fed8377a9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/RealmContentScannerStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/RealmContentScannerStore.kt @@ -32,12 +32,14 @@ import org.matrix.android.sdk.internal.di.ContentScannerDatabase import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.contentscanner.data.ContentScannerStore import org.matrix.android.sdk.internal.util.isValidUrl +import org.matrix.android.sdk.internal.util.time.Clock import javax.inject.Inject @SessionScope internal class RealmContentScannerStore @Inject constructor( @ContentScannerDatabase - private val realmConfiguration: RealmConfiguration + private val realmConfiguration: RealmConfiguration, + private val clock: Clock, ) : ContentScannerStore { private val monarchy = Monarchy.Builder() @@ -82,15 +84,15 @@ internal class RealmContentScannerStore @Inject constructor( override fun updateStateForContent(mxcUrl: String, state: ScanState, scannerUrl: String?) { monarchy.runTransactionSync { - ContentScanResultEntity.getOrCreate(it, mxcUrl, scannerUrl).scanResult = state + ContentScanResultEntity.getOrCreate(it, mxcUrl, scannerUrl, clock.epochMillis()).scanResult = state } } override fun updateScanResultForContent(mxcUrl: String, scannerUrl: String?, state: ScanState, humanReadable: String) { monarchy.runTransactionSync { - ContentScanResultEntity.getOrCreate(it, mxcUrl, scannerUrl).apply { + ContentScanResultEntity.getOrCreate(it, mxcUrl, scannerUrl, clock.epochMillis()).apply { scanResult = state - scanDateTimestamp = System.currentTimeMillis() + scanDateTimestamp = clock.epochMillis() humanReadableMessage = humanReadable } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt index 4a1e6661b0c8e8e19bd3d706d88238a8b21103e2..c138c1a40e666ee5e4d687b8228bccc028cac72d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt @@ -24,7 +24,7 @@ import javax.inject.Inject @SessionScope internal class DefaultSyncStatusService @Inject constructor() : - SyncStatusService, + SyncStatusService, ProgressReporter { private val status = MutableLiveData<SyncStatusService.Status>() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt index 30b1589169694d63bd8e0d34dc9c7c8e29646228..1b96931c6c8eaeaf3155ed298d6f73fbc076baca 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt @@ -59,7 +59,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri private val updateUserAccountDataTask: UpdateUserAccountDataTask, private val accountDataDataSource: UserAccountDataDataSource, private val widgetFactory: WidgetFactory) : - SessionLifecycleObserver { + SessionLifecycleObserver { private val currentConfigs = ArrayList<IntegrationManagerConfig>() private val lifecycleOwner: LifecycleOwner = LifecycleOwner { lifecycleRegistry } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt index dff82cb42e42a7e8407d9c7c9afed9d49993bcf2..d20cf8f140dd9d88594cc860c844d4c3ca16aa5a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt @@ -72,6 +72,7 @@ internal class ViaParameterFinder @Inject constructor( */ private fun getUserIdsOfJoinedMembers(roomId: String): Set<String> { return roomGetterProvider.get().getRoom(roomId) + ?.membershipService() ?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) }) ?.map { it.userId } .orEmpty() @@ -84,6 +85,7 @@ internal class ViaParameterFinder @Inject constructor( // It may not be possible for a user to join a room if there's no overlap between these fun computeViaParamsForRestricted(roomId: String, max: Int): List<String> { val userThatCanInvite = roomGetterProvider.get().getRoom(roomId) + ?.membershipService() ?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) }) ?.map { it.userId } ?.filter { userCanInvite(userId, roomId) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt index 6ff4efaf113d99a48dca182841ebc4ef69fa43ed..501aff63bd91b11c6455b270552198a9046081d6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt @@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse import org.matrix.android.sdk.api.session.identity.ThreePid +import org.matrix.android.sdk.api.session.uia.UiaResult import org.matrix.android.sdk.internal.auth.registration.handleUIA import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields @@ -72,13 +73,13 @@ internal class DefaultFinalizeAddingThreePidTask @Inject constructor( true } catch (throwable: Throwable) { if (params.userInteractiveAuthInterceptor == null || - !handleUIA( + handleUIA( failure = throwable, interceptor = params.userInteractiveAuthInterceptor, retryBlock = { authUpdate -> execute(params.copy(userAuthParam = authUpdate)) } - ) + ) != UiaResult.SUCCESS ) { Timber.d("## UIA: propagate failure") throw throwable.toRegistrationFlowResponse() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPushRuleTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPushRuleTask.kt index b2176871688bf631e5aa35f253169bc3ff0006d2..c46474cf90b951c8551abfd85f3dc27997796d91 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPushRuleTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPushRuleTask.kt @@ -15,8 +15,8 @@ */ package org.matrix.android.sdk.internal.session.pushers -import org.matrix.android.sdk.api.pushrules.RuleKind -import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.RuleKind +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPusherWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPusherWorker.kt index ce29efaaac5160fd750de83f14185777a97c6141..0042558027746ef4422dd337825a27c21aeb083b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPusherWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPusherWorker.kt @@ -26,7 +26,7 @@ import org.matrix.android.sdk.internal.worker.SessionWorkerParams import javax.inject.Inject internal class AddPusherWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<AddPusherWorker.Params>(context, params, sessionManager, Params::class.java) { + SessionSafeCoroutineWorker<AddPusherWorker.Params>(context, params, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultConditionResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultConditionResolver.kt index 84a05067bed8084b91a9fea1fef23ed27933c217..67fba390d00e1a5458060f005678a20a382fd047 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultConditionResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultConditionResolver.kt @@ -15,14 +15,15 @@ */ package org.matrix.android.sdk.internal.session.pushers -import org.matrix.android.sdk.api.pushrules.ConditionResolver -import org.matrix.android.sdk.api.pushrules.ContainsDisplayNameCondition -import org.matrix.android.sdk.api.pushrules.EventMatchCondition -import org.matrix.android.sdk.api.pushrules.RoomMemberCountCondition -import org.matrix.android.sdk.api.pushrules.SenderNotificationPermissionCondition import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.pushrules.ConditionResolver +import org.matrix.android.sdk.api.session.pushrules.ContainsDisplayNameCondition +import org.matrix.android.sdk.api.session.pushrules.EventMatchCondition +import org.matrix.android.sdk.api.session.pushrules.RoomMemberCountCondition +import org.matrix.android.sdk.api.session.pushrules.SenderNotificationPermissionCondition +import org.matrix.android.sdk.api.session.room.getStateEvent import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.room.RoomGetter @@ -60,7 +61,7 @@ internal class DefaultConditionResolver @Inject constructor( condition: ContainsDisplayNameCondition): Boolean { val roomId = event.roomId ?: return false val room = roomGetter.getRoom(roomId) ?: return false - val myDisplayName = room.getRoomMember(userId)?.displayName ?: return false + val myDisplayName = room.membershipService().getRoomMember(userId)?.displayName ?: return false return condition.isSatisfied(event, myDisplayName) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/GetPushRulesResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesResponse.kt similarity index 90% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/GetPushRulesResponse.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesResponse.kt index 35b4d77c0e4bc91a02552d6c998917810d4a9a96..de038196291efb2aca738291d6486cf9e2e09399 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/GetPushRulesResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/GetPushRulesResponse.kt @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules.rest +package org.matrix.android.sdk.internal.session.pushers import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.pushrules.rest.RuleSet /** * All push rulesets for a user. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushRulesApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushRulesApi.kt index 994b4860c6fd4511ca921a78ad7d09c1cc5ab3c3..dab6d373177b9f26062c70048d5be00c8a710633 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushRulesApi.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushRulesApi.kt @@ -15,8 +15,7 @@ */ package org.matrix.android.sdk.internal.session.pushers -import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse -import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule import org.matrix.android.sdk.internal.network.NetworkConstants import retrofit2.http.Body import retrofit2.http.DELETE diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt index d53a4eed65462a96b60c8db9a967ef0133d7ebd9..4528c95e6914d88e2b90b88edfc7d7221fb1a4ec 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt @@ -19,14 +19,14 @@ package org.matrix.android.sdk.internal.session.pushers import dagger.Binds import dagger.Module import dagger.Provides -import org.matrix.android.sdk.api.pushrules.ConditionResolver -import org.matrix.android.sdk.api.pushrules.PushRuleService import org.matrix.android.sdk.api.session.pushers.PushersService -import org.matrix.android.sdk.internal.session.notification.DefaultProcessEventForPushTask -import org.matrix.android.sdk.internal.session.notification.DefaultPushRuleService -import org.matrix.android.sdk.internal.session.notification.ProcessEventForPushTask +import org.matrix.android.sdk.api.session.pushrules.ConditionResolver +import org.matrix.android.sdk.api.session.pushrules.PushRuleService import org.matrix.android.sdk.internal.session.pushers.gateway.DefaultPushGatewayNotifyTask import org.matrix.android.sdk.internal.session.pushers.gateway.PushGatewayNotifyTask +import org.matrix.android.sdk.internal.session.pushrules.DefaultProcessEventForPushTask +import org.matrix.android.sdk.internal.session.pushrules.DefaultPushRuleService +import org.matrix.android.sdk.internal.session.pushrules.ProcessEventForPushTask import org.matrix.android.sdk.internal.session.room.notification.DefaultSetRoomNotificationStateTask import org.matrix.android.sdk.internal.session.room.notification.SetRoomNotificationStateTask import retrofit2.Retrofit diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePushRuleTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePushRuleTask.kt index bae893608bc0e6426b9a8b01e08b430f1ab2511f..9b0bf7934bf843e7e9ad2f0d4a2cfe346931ceab 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePushRuleTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/RemovePushRuleTask.kt @@ -15,7 +15,7 @@ */ package org.matrix.android.sdk.internal.session.pushers -import org.matrix.android.sdk.api.pushrules.RuleKind +import org.matrix.android.sdk.api.session.pushrules.RuleKind import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/SavePushRulesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/SavePushRulesTask.kt index 6a4b891ecffe36b6735b68ace3354e9425939da5..ff685e9281554754fe04128c17bd73e2aeeaaa4a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/SavePushRulesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/SavePushRulesTask.kt @@ -16,9 +16,8 @@ package org.matrix.android.sdk.internal.session.pushers import com.zhuinden.monarchy.Monarchy -import org.matrix.android.sdk.api.pushrules.RuleScope -import org.matrix.android.sdk.api.pushrules.RuleSetKey -import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse +import org.matrix.android.sdk.api.session.pushrules.RuleScope +import org.matrix.android.sdk.api.session.pushrules.RuleSetKey import org.matrix.android.sdk.internal.database.mapper.PushRulesMapper import org.matrix.android.sdk.internal.database.model.PushRulesEntity import org.matrix.android.sdk.internal.database.model.deleteOnCascade diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleActionsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleActionsTask.kt index 33589dc55bc5d384eaf6c0392038175261810b82..454b9cdd80b8fb6a9a966a0b80e03fcd5d4137a9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleActionsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleActionsTask.kt @@ -15,9 +15,9 @@ */ package org.matrix.android.sdk.internal.session.pushers -import org.matrix.android.sdk.api.pushrules.Action -import org.matrix.android.sdk.api.pushrules.RuleKind -import org.matrix.android.sdk.api.pushrules.toJson +import org.matrix.android.sdk.api.session.pushrules.Action +import org.matrix.android.sdk.api.session.pushrules.RuleKind +import org.matrix.android.sdk.api.session.pushrules.toJson import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task @@ -38,18 +38,18 @@ internal class DefaultUpdatePushRuleActionsTask @Inject constructor( ) : UpdatePushRuleActionsTask { override suspend fun execute(params: UpdatePushRuleActionsTask.Params) { + executeRequest(globalErrorReceiver) { + pushRulesApi.updateEnableRuleStatus( + params.kind.value, + params.ruleId, + EnabledBody(params.enable) + ) + } + if (params.actions != null) { + val body = mapOf("actions" to params.actions.toJson()) executeRequest(globalErrorReceiver) { - pushRulesApi.updateEnableRuleStatus( - params.kind.value, - params.ruleId, - EnabledBody(params.enable) - ) - } - if (params.actions != null) { - val body = mapOf("actions" to params.actions.toJson()) - executeRequest(globalErrorReceiver) { - pushRulesApi.updateRuleActions(params.kind.value, params.ruleId, body) - } + pushRulesApi.updateRuleActions(params.kind.value, params.ruleId, body) } + } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleEnableStatusTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleEnableStatusTask.kt index 3fe1614678b302d7e8fd361cb021fa6af1dde2ff..815661a1ce9863170b2d10e29ee6aa120f8b1d9c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleEnableStatusTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/UpdatePushRuleEnableStatusTask.kt @@ -15,8 +15,8 @@ */ package org.matrix.android.sdk.internal.session.pushers -import org.matrix.android.sdk.api.pushrules.RuleKind -import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.RuleKind +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/DefaultPushRuleService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/DefaultPushRuleService.kt similarity index 90% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/DefaultPushRuleService.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/DefaultPushRuleService.kt index cdc7350f8bcde907aef51c8d5640e67502a36a66..ace23f1fe5e8cdd8a64fbdeedadbcb5b8b908e73 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/DefaultPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/DefaultPushRuleService.kt @@ -13,23 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.session.notification +package org.matrix.android.sdk.internal.session.pushrules import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations import com.zhuinden.monarchy.Monarchy -import org.matrix.android.sdk.api.pushrules.Action -import org.matrix.android.sdk.api.pushrules.ConditionResolver -import org.matrix.android.sdk.api.pushrules.PushEvents -import org.matrix.android.sdk.api.pushrules.PushRuleService -import org.matrix.android.sdk.api.pushrules.RuleKind -import org.matrix.android.sdk.api.pushrules.RuleScope -import org.matrix.android.sdk.api.pushrules.RuleSetKey -import org.matrix.android.sdk.api.pushrules.SenderNotificationPermissionCondition -import org.matrix.android.sdk.api.pushrules.getActions -import org.matrix.android.sdk.api.pushrules.rest.PushRule -import org.matrix.android.sdk.api.pushrules.rest.RuleSet import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.pushrules.Action +import org.matrix.android.sdk.api.session.pushrules.ConditionResolver +import org.matrix.android.sdk.api.session.pushrules.PushEvents +import org.matrix.android.sdk.api.session.pushrules.PushRuleService +import org.matrix.android.sdk.api.session.pushrules.RuleKind +import org.matrix.android.sdk.api.session.pushrules.RuleScope +import org.matrix.android.sdk.api.session.pushrules.RuleSetKey +import org.matrix.android.sdk.api.session.pushrules.SenderNotificationPermissionCondition +import org.matrix.android.sdk.api.session.pushrules.getActions +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.rest.RuleSet import org.matrix.android.sdk.internal.database.mapper.PushRulesMapper import org.matrix.android.sdk.internal.database.model.PushRuleEntity import org.matrix.android.sdk.internal.database.model.PushRulesEntity diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/ProcessEventForPushTask.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/ProcessEventForPushTask.kt index 899bce4c8ddf318effb7c810ff6fae207b768702..91d092a2b4b552f9b2e1185f01d24a1fb07edbe3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/ProcessEventForPushTask.kt @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.notification +package org.matrix.android.sdk.internal.session.pushrules -import org.matrix.android.sdk.api.pushrules.PushEvents -import org.matrix.android.sdk.api.pushrules.rest.PushRule import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.isInvitation +import org.matrix.android.sdk.api.session.pushrules.PushEvents +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/PushRuleFinder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/PushRuleFinder.kt similarity index 86% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/PushRuleFinder.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/PushRuleFinder.kt index 6e302d373d819dfe5944685165bd39c06200c729..b9d06a934dd628ca5a05d824897b1c2d0846f3d7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/PushRuleFinder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/PushRuleFinder.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.notification +package org.matrix.android.sdk.internal.session.pushrules -import org.matrix.android.sdk.api.pushrules.ConditionResolver -import org.matrix.android.sdk.api.pushrules.rest.PushRule import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.pushrules.ConditionResolver +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule import javax.inject.Inject internal class PushRuleFinder @Inject constructor( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt index 3f129c4d71be31af769053f0979d085610086b72..7326adee4c7a1a1d68ad1a3283046c57f3056606 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt @@ -18,13 +18,11 @@ package org.matrix.android.sdk.internal.session.room import androidx.lifecycle.LiveData import org.matrix.android.sdk.api.MatrixCoroutineDispatchers -import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM -import org.matrix.android.sdk.api.session.crypto.CryptoService -import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataService import org.matrix.android.sdk.api.session.room.alias.AliasService import org.matrix.android.sdk.api.session.room.call.RoomCallService +import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService import org.matrix.android.sdk.api.session.room.members.MembershipService import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomType @@ -42,62 +40,37 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineService import org.matrix.android.sdk.api.session.room.typing.TypingService import org.matrix.android.sdk.api.session.room.uploads.UploadsService import org.matrix.android.sdk.api.session.room.version.RoomVersionService -import org.matrix.android.sdk.api.session.search.SearchResult import org.matrix.android.sdk.api.session.space.Space import org.matrix.android.sdk.api.util.Optional -import org.matrix.android.sdk.api.util.awaitCallback import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder -import org.matrix.android.sdk.internal.session.room.state.SendStateTask import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource -import org.matrix.android.sdk.internal.session.search.SearchTask import org.matrix.android.sdk.internal.session.space.DefaultSpace -import java.security.InvalidParameterException -internal class DefaultRoom(override val roomId: String, - private val roomSummaryDataSource: RoomSummaryDataSource, - private val timelineService: TimelineService, - private val threadsService: ThreadsService, - private val threadsLocalService: ThreadsLocalService, - private val sendService: SendService, - private val draftService: DraftService, - private val stateService: StateService, - private val uploadsService: UploadsService, - private val reportingService: ReportingService, - private val roomCallService: RoomCallService, - private val readService: ReadService, - private val typingService: TypingService, - private val aliasService: AliasService, - private val tagsService: TagsService, - private val cryptoService: CryptoService, - private val relationService: RelationService, - private val roomMembersService: MembershipService, - private val roomPushRuleService: RoomPushRuleService, - private val roomAccountDataService: RoomAccountDataService, - private val roomVersionService: RoomVersionService, - private val sendStateTask: SendStateTask, - private val viaParameterFinder: ViaParameterFinder, - private val searchTask: SearchTask, - override val coroutineDispatchers: MatrixCoroutineDispatchers -) : - Room, - TimelineService by timelineService, - ThreadsService by threadsService, - ThreadsLocalService by threadsLocalService, - SendService by sendService, - DraftService by draftService, - StateService by stateService, - UploadsService by uploadsService, - ReportingService by reportingService, - RoomCallService by roomCallService, - ReadService by readService, - TypingService by typingService, - AliasService by aliasService, - TagsService by tagsService, - RelationService by relationService, - MembershipService by roomMembersService, - RoomPushRuleService by roomPushRuleService, - RoomAccountDataService by roomAccountDataService, - RoomVersionService by roomVersionService { +internal class DefaultRoom( + override val roomId: String, + private val roomSummaryDataSource: RoomSummaryDataSource, + private val roomCryptoService: RoomCryptoService, + private val timelineService: TimelineService, + private val threadsService: ThreadsService, + private val threadsLocalService: ThreadsLocalService, + private val sendService: SendService, + private val draftService: DraftService, + private val stateService: StateService, + private val uploadsService: UploadsService, + private val reportingService: ReportingService, + private val roomCallService: RoomCallService, + private val readService: ReadService, + private val typingService: TypingService, + private val aliasService: AliasService, + private val tagsService: TagsService, + private val relationService: RelationService, + private val roomMembersService: MembershipService, + private val roomPushRuleService: RoomPushRuleService, + private val roomAccountDataService: RoomAccountDataService, + private val roomVersionService: RoomVersionService, + private val viaParameterFinder: ViaParameterFinder, + override val coroutineDispatchers: MatrixCoroutineDispatchers +) : Room { override fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>> { return roomSummaryDataSource.getRoomSummaryLive(roomId) @@ -107,69 +80,28 @@ internal class DefaultRoom(override val roomId: String, return roomSummaryDataSource.getRoomSummary(roomId) } - override fun isEncrypted(): Boolean { - return cryptoService.isRoomEncrypted(roomId) - } - - override fun encryptionAlgorithm(): String? { - return cryptoService.getEncryptionAlgorithm(roomId) - } - - override fun shouldEncryptForInvitedMembers(): Boolean { - return cryptoService.shouldEncryptForInvitedMembers(roomId) - } - - override suspend fun prepareToEncrypt() { - awaitCallback<Unit> { - cryptoService.prepareToEncrypt(roomId, it) - } - } - - override suspend fun enableEncryption(algorithm: String, force: Boolean) { - when { - (!force && isEncrypted() && encryptionAlgorithm() == MXCRYPTO_ALGORITHM_MEGOLM) -> { - throw IllegalStateException("Encryption is already enabled for this room") - } - (!force && algorithm != MXCRYPTO_ALGORITHM_MEGOLM) -> { - throw InvalidParameterException("Only MXCRYPTO_ALGORITHM_MEGOLM algorithm is supported") - } - else -> { - val params = SendStateTask.Params( - roomId = roomId, - stateKey = "", - eventType = EventType.STATE_ROOM_ENCRYPTION, - body = mapOf( - "algorithm" to algorithm - )) - - sendStateTask.execute(params) - } - } - } - - override suspend fun search(searchTerm: String, - nextBatch: String?, - orderByRecent: Boolean, - limit: Int, - beforeLimit: Int, - afterLimit: Int, - includeProfile: Boolean): SearchResult { - return searchTask.execute( - SearchTask.Params( - searchTerm = searchTerm, - roomId = roomId, - nextBatch = nextBatch, - orderByRecent = orderByRecent, - limit = limit, - beforeLimit = beforeLimit, - afterLimit = afterLimit, - includeProfile = includeProfile - ) - ) - } - override fun asSpace(): Space? { if (roomSummary()?.roomType != RoomType.SPACE) return null return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder) } + + override fun timelineService() = timelineService + override fun threadsService() = threadsService + override fun threadsLocalService() = threadsLocalService + override fun sendService() = sendService + override fun draftService() = draftService + override fun stateService() = stateService + override fun uploadsService() = uploadsService + override fun reportingService() = reportingService + override fun roomCallService() = roomCallService + override fun readService() = readService + override fun typingService() = typingService + override fun aliasService() = aliasService + override fun tagsService() = tagsService + override fun relationService() = relationService + override fun roomCryptoService() = roomCryptoService + override fun membershipService() = roomMembersService + override fun roomPushRuleService() = roomPushRuleService + override fun roomAccountDataService() = roomAccountDataService + override fun roomVersionService() = roomVersionService } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt index 15ce5810c812abf53427dfc0502bd16cfdbd7417..7e0b44a3149fd0bce90e99f1f049c8dc016ec5d2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt @@ -28,14 +28,16 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon import org.matrix.android.sdk.api.session.events.model.getRelationContent import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.model.PollSummaryContent import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent import org.matrix.android.sdk.api.session.room.model.VoteInfo import org.matrix.android.sdk.api.session.room.model.VoteSummary +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent -import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent @@ -67,6 +69,7 @@ import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.LiveLocationAggregationProcessor import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject @@ -75,7 +78,8 @@ internal class EventRelationsAggregationProcessor @Inject constructor( private val stateEventDataSource: StateEventDataSource, @SessionId private val sessionId: String, private val sessionManager: SessionManager, - private val liveLocationAggregationProcessor: LiveLocationAggregationProcessor + private val liveLocationAggregationProcessor: LiveLocationAggregationProcessor, + private val clock: Clock, ) : EventInsertLiveProcessor { private val allowedTypes = listOf( @@ -91,7 +95,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( // EventType.KEY_VERIFICATION_READY, EventType.KEY_VERIFICATION_KEY, EventType.ENCRYPTED - ) + EventType.POLL_START + EventType.POLL_RESPONSE + EventType.POLL_END + EventType.BEACON_LOCATION_DATA + ) + EventType.POLL_START + EventType.POLL_RESPONSE + EventType.POLL_END + EventType.STATE_ROOM_BEACON_INFO + EventType.BEACON_LOCATION_DATA override fun shouldProcess(eventId: String, eventType: String, insertType: EventInsertType): Boolean { return allowedTypes.contains(eventType) @@ -106,12 +110,12 @@ internal class EventRelationsAggregationProcessor @Inject constructor( } val isLocalEcho = LocalEcho.isLocalEchoId(event.eventId ?: "") when (event.type) { - EventType.REACTION -> { + EventType.REACTION -> { // we got a reaction!! Timber.v("###REACTION in room $roomId , reaction eventID ${event.eventId}") handleReaction(realm, event, roomId, isLocalEcho) } - EventType.MESSAGE -> { + EventType.MESSAGE -> { if (event.unsignedData?.relations?.annotations != null) { Timber.v("###REACTION Aggregation in room $roomId for event ${event.eventId}") handleInitialAggregatedRelations(realm, event, roomId, event.unsignedData.relations.annotations) @@ -137,7 +141,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( EventType.KEY_VERIFICATION_START, EventType.KEY_VERIFICATION_MAC, EventType.KEY_VERIFICATION_READY, - EventType.KEY_VERIFICATION_KEY -> { + EventType.KEY_VERIFICATION_KEY -> { Timber.v("## SAS REF in room $roomId for event ${event.eventId}") event.content.toModel<MessageRelationContent>()?.relatesTo?.let { if (it.type == RelationType.REFERENCE && it.eventId != null) { @@ -146,7 +150,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( } } - EventType.ENCRYPTED -> { + EventType.ENCRYPTED -> { // Relation type is in clear val encryptedEventContent = event.content.toModel<EncryptedEventContent>() if (encryptedEventContent?.relatesTo?.type == RelationType.REPLACE || @@ -189,8 +193,8 @@ internal class EventRelationsAggregationProcessor @Inject constructor( } } in EventType.BEACON_LOCATION_DATA -> { - event.content.toModel<MessageLiveLocationContent>(catchError = true)?.let { - liveLocationAggregationProcessor.handleLiveLocation(realm, event, it, roomId, isLocalEcho) + event.getClearContent().toModel<MessageBeaconLocationDataContent>(catchError = true)?.let { + liveLocationAggregationProcessor.handleBeaconLocationData(realm, event, it, roomId, isLocalEcho) } } } @@ -213,7 +217,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( // } // } } - EventType.REDACTION -> { + EventType.REDACTION -> { val eventToPrune = event.redacts?.let { EventEntity.where(realm, eventId = it).findFirst() } ?: return when (eventToPrune.type) { @@ -233,7 +237,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( } } } - in EventType.POLL_START -> { + in EventType.POLL_START -> { val content: MessagePollContent? = event.content.toModel() if (content?.relatesTo?.type == RelationType.REPLACE) { Timber.v("###REPLACE in room $roomId for event ${event.eventId}") @@ -241,22 +245,22 @@ internal class EventRelationsAggregationProcessor @Inject constructor( handleReplace(realm, event, content, roomId, isLocalEcho) } } - in EventType.POLL_RESPONSE -> { + in EventType.POLL_RESPONSE -> { event.content.toModel<MessagePollResponseContent>(catchError = true)?.let { handleResponse(realm, event, it, roomId, isLocalEcho) } } - in EventType.POLL_END -> { + in EventType.POLL_END -> { event.content.toModel<MessageEndPollContent>(catchError = true)?.let { handleEndPoll(realm, event, it, roomId, isLocalEcho) } } - in EventType.BEACON_LOCATION_DATA -> { - event.content.toModel<MessageLiveLocationContent>(catchError = true)?.let { - liveLocationAggregationProcessor.handleLiveLocation(realm, event, it, roomId, isLocalEcho) + in EventType.STATE_ROOM_BEACON_INFO -> { + event.content.toModel<MessageBeaconInfoContent>(catchError = true)?.let { + liveLocationAggregationProcessor.handleBeaconInfo(realm, event, it, roomId, isLocalEcho) } } - else -> Timber.v("UnHandled event ${event.eventId}") + else -> Timber.v("UnHandled event ${event.eventId}") } } catch (t: Throwable) { Timber.e(t, "## Should not happen ") @@ -325,7 +329,8 @@ internal class EventRelationsAggregationProcessor @Inject constructor( totalVotes = 0, winnerVoteCount = 0, ) - .toContent()) + .toContent() + ) } val txId = event.unsignedData?.transactionId @@ -335,7 +340,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( Timber.v("###REPLACE Receiving remote echo of edit (edit already done)") existingSummary.editions.firstOrNull { it.eventId == txId }?.let { it.eventId = event.eventId - it.timestamp = event.originServerTs ?: System.currentTimeMillis() + it.timestamp = event.originServerTs ?: clock.epochMillis() it.isLocalEcho = false } } else { @@ -346,10 +351,10 @@ internal class EventRelationsAggregationProcessor @Inject constructor( eventId = event.eventId, content = ContentMapper.map(newContent), timestamp = if (isLocalEcho) { - System.currentTimeMillis() + clock.epochMillis() } else { // Do not take local echo originServerTs here, could mess up ordering (keep old ts) - event.originServerTs ?: System.currentTimeMillis() + event.originServerTs ?: clock.epochMillis() }, isLocalEcho = isLocalEcho ) @@ -542,7 +547,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( private fun getPollEvent(roomId: String, eventId: String): TimelineEvent? { val session = sessionManager.getSessionComponent(sessionId)?.session() - return session?.getRoom(roomId)?.getTimelineEvent(eventId) ?: return null.also { + return session?.roomService()?.getRoom(roomId)?.getTimelineEvent(eventId) ?: return null.also { Timber.v("## POLL target poll event $eventId not found in room $roomId") } } @@ -729,11 +734,13 @@ internal class EventRelationsAggregationProcessor @Inject constructor( EventType.KEY_VERIFICATION_READY, EventType.KEY_VERIFICATION_KEY, EventType.KEY_VERIFICATION_MAC -> currentState.toState(VerificationState.WAITING) - EventType.KEY_VERIFICATION_CANCEL -> currentState.toState(if (event.senderId == userId) { - VerificationState.CANCELED_BY_ME - } else { - VerificationState.CANCELED_BY_OTHER - }) + EventType.KEY_VERIFICATION_CANCEL -> currentState.toState( + if (event.senderId == userId) { + VerificationState.CANCELED_BY_ME + } else { + VerificationState.CANCELED_BY_OTHER + } + ) EventType.KEY_VERIFICATION_DONE -> currentState.toState(VerificationState.DONE) else -> VerificationState.REQUEST } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt index 10f75473b71e3256c85e486bcf9238a4b6bf57f2..65ef94999fc2e79b43aeda24cd56f79d987f0c0f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt @@ -194,7 +194,8 @@ internal interface RoomAPI { @PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/state/{state_event_type}") suspend fun sendStateEvent(@Path("roomId") roomId: String, @Path("state_event_type") stateEventType: String, - @Body params: JsonDict) + @Body params: JsonDict + ): SendResponse /** * Send a generic state event @@ -208,7 +209,8 @@ internal interface RoomAPI { suspend fun sendStateEvent(@Path("roomId") roomId: String, @Path("state_event_type") stateEventType: String, @Path("state_key") stateKey: String, - @Body params: JsonDict) + @Body params: JsonDict + ): SendResponse /** * Get state events of a room diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt index 72a3f9ab22036910d5624c0aa109fc47ab194cad..01c4fd1501dba0eb9895409b8d7a8e36f509e7f6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt @@ -17,13 +17,13 @@ package org.matrix.android.sdk.internal.session.room import org.matrix.android.sdk.api.MatrixCoroutineDispatchers -import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder import org.matrix.android.sdk.internal.session.room.accountdata.DefaultRoomAccountDataService import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService +import org.matrix.android.sdk.internal.session.room.crypto.DefaultRoomCryptoService import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService import org.matrix.android.sdk.internal.session.room.membership.DefaultMembershipService import org.matrix.android.sdk.internal.session.room.notification.DefaultRoomPushRuleService @@ -32,7 +32,6 @@ import org.matrix.android.sdk.internal.session.room.relation.DefaultRelationServ import org.matrix.android.sdk.internal.session.room.reporting.DefaultReportingService import org.matrix.android.sdk.internal.session.room.send.DefaultSendService import org.matrix.android.sdk.internal.session.room.state.DefaultStateService -import org.matrix.android.sdk.internal.session.room.state.SendStateTask import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource import org.matrix.android.sdk.internal.session.room.tags.DefaultTagsService import org.matrix.android.sdk.internal.session.room.threads.DefaultThreadsService @@ -41,7 +40,6 @@ import org.matrix.android.sdk.internal.session.room.timeline.DefaultTimelineServ import org.matrix.android.sdk.internal.session.room.typing.DefaultTypingService import org.matrix.android.sdk.internal.session.room.uploads.DefaultUploadsService import org.matrix.android.sdk.internal.session.room.version.DefaultRoomVersionService -import org.matrix.android.sdk.internal.session.search.SearchTask import javax.inject.Inject internal interface RoomFactory { @@ -49,36 +47,36 @@ internal interface RoomFactory { } @SessionScope -internal class DefaultRoomFactory @Inject constructor(private val cryptoService: CryptoService, - private val roomSummaryDataSource: RoomSummaryDataSource, - private val timelineServiceFactory: DefaultTimelineService.Factory, - private val threadsServiceFactory: DefaultThreadsService.Factory, - private val threadsLocalServiceFactory: DefaultThreadsLocalService.Factory, - private val sendServiceFactory: DefaultSendService.Factory, - private val draftServiceFactory: DefaultDraftService.Factory, - private val stateServiceFactory: DefaultStateService.Factory, - private val uploadsServiceFactory: DefaultUploadsService.Factory, - private val reportingServiceFactory: DefaultReportingService.Factory, - private val roomCallServiceFactory: DefaultRoomCallService.Factory, - private val readServiceFactory: DefaultReadService.Factory, - private val typingServiceFactory: DefaultTypingService.Factory, - private val aliasServiceFactory: DefaultAliasService.Factory, - private val tagsServiceFactory: DefaultTagsService.Factory, - private val relationServiceFactory: DefaultRelationService.Factory, - private val membershipServiceFactory: DefaultMembershipService.Factory, - private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory, - private val roomVersionServiceFactory: DefaultRoomVersionService.Factory, - private val roomAccountDataServiceFactory: DefaultRoomAccountDataService.Factory, - private val sendStateTask: SendStateTask, - private val viaParameterFinder: ViaParameterFinder, - private val searchTask: SearchTask, - private val coroutineDispatchers: MatrixCoroutineDispatchers) : - RoomFactory { +internal class DefaultRoomFactory @Inject constructor( + private val roomSummaryDataSource: RoomSummaryDataSource, + private val timelineServiceFactory: DefaultTimelineService.Factory, + private val threadsServiceFactory: DefaultThreadsService.Factory, + private val threadsLocalServiceFactory: DefaultThreadsLocalService.Factory, + private val sendServiceFactory: DefaultSendService.Factory, + private val draftServiceFactory: DefaultDraftService.Factory, + private val stateServiceFactory: DefaultStateService.Factory, + private val uploadsServiceFactory: DefaultUploadsService.Factory, + private val reportingServiceFactory: DefaultReportingService.Factory, + private val roomCallServiceFactory: DefaultRoomCallService.Factory, + private val readServiceFactory: DefaultReadService.Factory, + private val typingServiceFactory: DefaultTypingService.Factory, + private val aliasServiceFactory: DefaultAliasService.Factory, + private val tagsServiceFactory: DefaultTagsService.Factory, + private val relationServiceFactory: DefaultRelationService.Factory, + private val roomCryptoServiceFactory: DefaultRoomCryptoService.Factory, + private val membershipServiceFactory: DefaultMembershipService.Factory, + private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory, + private val roomVersionServiceFactory: DefaultRoomVersionService.Factory, + private val roomAccountDataServiceFactory: DefaultRoomAccountDataService.Factory, + private val viaParameterFinder: ViaParameterFinder, + private val coroutineDispatchers: MatrixCoroutineDispatchers +) : RoomFactory { override fun create(roomId: String): Room { return DefaultRoom( roomId = roomId, roomSummaryDataSource = roomSummaryDataSource, + roomCryptoService = roomCryptoServiceFactory.create(roomId), timelineService = timelineServiceFactory.create(roomId), threadsService = threadsServiceFactory.create(roomId), threadsLocalService = threadsLocalServiceFactory.create(roomId), @@ -92,14 +90,11 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService: typingService = typingServiceFactory.create(roomId), aliasService = aliasServiceFactory.create(roomId), tagsService = tagsServiceFactory.create(roomId), - cryptoService = cryptoService, relationService = relationServiceFactory.create(roomId), roomMembersService = membershipServiceFactory.create(roomId), roomPushRuleService = roomPushRuleServiceFactory.create(roomId), roomAccountDataService = roomAccountDataServiceFactory.create(roomId), roomVersionService = roomVersionServiceFactory.create(roomId), - sendStateTask = sendStateTask, - searchTask = searchTask, viaParameterFinder = viaParameterFinder, coroutineDispatchers = coroutineDispatchers ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/DefaultLiveLocationAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/DefaultLiveLocationAggregationProcessor.kt index 95e196c7621303292ce101357c20596daf38fabc..997e31a1091e51b62c75d8086225d60e0346d252 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/DefaultLiveLocationAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/DefaultLiveLocationAggregationProcessor.kt @@ -17,69 +17,78 @@ package org.matrix.android.sdk.internal.session.room.aggregation.livelocation import io.realm.Realm -import org.matrix.android.sdk.api.extensions.orFalse +import org.matrix.android.sdk.api.extensions.orTrue import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationBeaconContent -import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent import org.matrix.android.sdk.internal.database.mapper.ContentMapper -import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity -import org.matrix.android.sdk.internal.database.query.getOrNull +import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity +import org.matrix.android.sdk.internal.database.query.getOrCreate import timber.log.Timber import javax.inject.Inject internal class DefaultLiveLocationAggregationProcessor @Inject constructor() : LiveLocationAggregationProcessor { - override fun handleLiveLocation(realm: Realm, event: Event, content: MessageLiveLocationContent, roomId: String, isLocalEcho: Boolean) { - val locationSenderId = event.senderId ?: return - - // We shouldn't process local echos - if (isLocalEcho) { + override fun handleBeaconInfo(realm: Realm, event: Event, content: MessageBeaconInfoContent, roomId: String, isLocalEcho: Boolean) { + if (event.senderId.isNullOrEmpty() || isLocalEcho) { return } - // A beacon info state event has to be sent before sending location - // TODO handle missing check of m_relatesTo field - var beaconInfoEntity: CurrentStateEventEntity? = null - val eventTypesIterator = EventType.STATE_ROOM_BEACON_INFO.iterator() - while (beaconInfoEntity == null && eventTypesIterator.hasNext()) { - beaconInfoEntity = CurrentStateEventEntity.getOrNull(realm, roomId, locationSenderId, eventTypesIterator.next()) + val targetEventId = if (content.isLive.orTrue()) { + event.eventId + } else { + // when live is set to false, we use the id of the event that should have been replaced + event.unsignedData?.replacesState } - if (beaconInfoEntity == null) { - Timber.v("## LIVE LOCATION. There is not any beacon info which should be emitted before sending location updates") + if (targetEventId.isNullOrEmpty()) { + Timber.w("no target event id found for the beacon content") return } - val beaconInfoContent = ContentMapper.map(beaconInfoEntity.root?.content)?.toModel<LiveLocationBeaconContent>(catchError = true) - if (beaconInfoContent == null) { - Timber.v("## LIVE LOCATION. Beacon info content is invalid") + + val aggregatedSummary = LiveLocationShareAggregatedSummaryEntity.getOrCreate( + realm = realm, + roomId = roomId, + eventId = targetEventId + ) + + Timber.d("updating summary of id=$targetEventId with isLive=${content.isLive}") + + aggregatedSummary.endOfLiveTimestampMillis = content.getBestTimestampMillis()?.let { it + (content.timeout ?: 0) } + aggregatedSummary.isActive = content.isLive + } + + override fun handleBeaconLocationData(realm: Realm, event: Event, content: MessageBeaconLocationDataContent, roomId: String, isLocalEcho: Boolean) { + if (event.senderId.isNullOrEmpty() || isLocalEcho) { return } - // Check if live location is ended - if (!beaconInfoContent.getBestBeaconInfo()?.isLive.orFalse()) { - Timber.v("## LIVE LOCATION. Beacon info is not live anymore") + val targetEventId = content.relatesTo?.eventId + + if (targetEventId.isNullOrEmpty()) { + Timber.w("no target event id found for the live location content") return } - // Check if beacon info is outdated - if (isBeaconInfoOutdated(beaconInfoContent, content)) { - Timber.v("## LIVE LOCATION. Beacon info has timeout") - beaconInfoContent.hasTimedOut = true - } else { - beaconInfoContent.lastLocationContent = content - } + val aggregatedSummary = LiveLocationShareAggregatedSummaryEntity.getOrCreate( + realm = realm, + roomId = roomId, + eventId = targetEventId + ) + val updatedLocationTimestamp = content.getBestTimestampMillis() ?: 0 + val currentLocationTimestamp = ContentMapper + .map(aggregatedSummary.lastLocationContent) + .toModel<MessageBeaconLocationDataContent>() + ?.getBestTimestampMillis() + ?: 0 - beaconInfoEntity.root?.content = ContentMapper.map(beaconInfoContent.toContent()) + if (updatedLocationTimestamp.isMoreRecentThan(currentLocationTimestamp)) { + Timber.d("updating last location of the summary of id=$targetEventId") + aggregatedSummary.lastLocationContent = ContentMapper.map(content.toContent()) + } } - private fun isBeaconInfoOutdated(beaconInfoContent: LiveLocationBeaconContent, - liveLocationContent: MessageLiveLocationContent): Boolean { - val beaconInfoStartTime = beaconInfoContent.getBestTimestampAsMilliseconds() ?: 0 - val liveLocationEventTime = liveLocationContent.getBestTimestampAsMilliseconds() ?: 0 - val timeout = beaconInfoContent.getBestBeaconInfo()?.timeout ?: 0 - return liveLocationEventTime - beaconInfoStartTime > timeout - } + private fun Long.isMoreRecentThan(timestamp: Long) = this > timestamp } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt index 7b5f23e2433cf7c567642a7e9c416a1759cff48b..c0be96f83d6af59a3084055df0bc7b89f6bdccce 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt @@ -18,12 +18,23 @@ package org.matrix.android.sdk.internal.session.room.aggregation.livelocation import io.realm.Realm import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent internal interface LiveLocationAggregationProcessor { - fun handleLiveLocation(realm: Realm, - event: Event, - content: MessageLiveLocationContent, - roomId: String, - isLocalEcho: Boolean) + fun handleBeaconInfo( + realm: Realm, + event: Event, + content: MessageBeaconInfoContent, + roomId: String, + isLocalEcho: Boolean, + ) + + fun handleBeaconLocationData( + realm: Realm, + event: Event, + content: MessageBeaconLocationDataContent, + roomId: String, + isLocalEcho: Boolean, + ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt index dc3ea55a019854d675f1f1a11341ee72128ed6ec..b25ef7ba0f8f357432f7d73905dc0b728bef3e13 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt @@ -52,7 +52,7 @@ internal class DefaultGetRoomIdByAliasTask @Inject constructor( } else if (!params.searchOnServer) { Optional.from(null) } else { - val description = tryOrNull("## Failed to get roomId from alias") { + val description = tryOrNull("## Failed to get roomId from alias") { executeRequest(globalErrorReceiver) { directoryAPI.getRoomIdByAlias(params.roomAlias) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt index 9bd15a02671487dadf0ce21d14d6f9d299a86812..6dd2c91048519738626cd6e85fc5db4e2ff72aca 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomTask.kt @@ -41,6 +41,7 @@ import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelpe import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction +import org.matrix.android.sdk.internal.util.time.Clock import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -56,7 +57,8 @@ internal class DefaultCreateRoomTask @Inject constructor( @SessionDatabase private val realmConfiguration: RealmConfiguration, private val createRoomBodyBuilder: CreateRoomBodyBuilder, - private val globalErrorReceiver: GlobalErrorReceiver + private val globalErrorReceiver: GlobalErrorReceiver, + private val clock: Clock, ) : CreateRoomTask { override suspend fun execute(params: CreateRoomParams): String { @@ -106,7 +108,7 @@ internal class DefaultCreateRoomTask @Inject constructor( } awaitTransaction(realmConfiguration) { - RoomSummaryEntity.where(it, roomId).findFirst()?.lastActivityTime = System.currentTimeMillis() + RoomSummaryEntity.where(it, roomId).findFirst()?.lastActivityTime = clock.epochMillis() } if (otherUserId != null) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/crypto/DefaultRoomCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/crypto/DefaultRoomCryptoService.kt new file mode 100644 index 0000000000000000000000000000000000000000..2546c58cc7c64974d3b3a5b921651fc1614ea435 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/crypto/DefaultRoomCryptoService.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022 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.internal.session.room.crypto + +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.session.crypto.CryptoService +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService +import org.matrix.android.sdk.api.util.awaitCallback +import org.matrix.android.sdk.internal.session.room.state.SendStateTask +import java.security.InvalidParameterException + +internal class DefaultRoomCryptoService @AssistedInject constructor( + @Assisted private val roomId: String, + private val cryptoService: CryptoService, + private val sendStateTask: SendStateTask, +) : RoomCryptoService { + + @AssistedFactory + interface Factory { + fun create(roomId: String): DefaultRoomCryptoService + } + + override fun isEncrypted(): Boolean { + return cryptoService.isRoomEncrypted(roomId) + } + + override fun encryptionAlgorithm(): String? { + return cryptoService.getEncryptionAlgorithm(roomId) + } + + override fun shouldEncryptForInvitedMembers(): Boolean { + return cryptoService.shouldEncryptForInvitedMembers(roomId) + } + + override suspend fun prepareToEncrypt() { + awaitCallback<Unit> { + cryptoService.prepareToEncrypt(roomId, it) + } + } + + override suspend fun enableEncryption(algorithm: String, force: Boolean) { + when { + (!force && isEncrypted() && encryptionAlgorithm() == MXCRYPTO_ALGORITHM_MEGOLM) -> { + throw IllegalStateException("Encryption is already enabled for this room") + } + (!force && algorithm != MXCRYPTO_ALGORITHM_MEGOLM) -> { + throw InvalidParameterException("Only MXCRYPTO_ALGORITHM_MEGOLM algorithm is supported") + } + else -> { + val params = SendStateTask.Params( + roomId = roomId, + stateKey = "", + eventType = EventType.STATE_ROOM_ENCRYPTION, + body = mapOf( + "algorithm" to algorithm + ) + ) + + sendStateTask.execute(params) + } + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt index 70ba9287a2a37dee85f8f0c5c16463a80f774f4e..d3d1cb856a05e970a85ac891dbc730058d1f9475 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt @@ -42,6 +42,7 @@ import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater import org.matrix.android.sdk.internal.session.sync.SyncTokenStore import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction +import org.matrix.android.sdk.internal.util.time.Clock import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -61,7 +62,8 @@ internal class DefaultLoadRoomMembersTask @Inject constructor( private val roomMemberEventHandler: RoomMemberEventHandler, private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, private val deviceListManager: DeviceListManager, - private val globalErrorReceiver: GlobalErrorReceiver + private val globalErrorReceiver: GlobalErrorReceiver, + private val clock: Clock, ) : LoadRoomMembersTask { override suspend fun execute(params: LoadRoomMembersTask.Params) { @@ -107,7 +109,7 @@ internal class DefaultLoadRoomMembersTask @Inject constructor( // We ignore all the already known members val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId) - val now = System.currentTimeMillis() + val now = clock.epochMillis() for (roomMemberEvent in response.roomMemberEvents) { if (roomMemberEvent.eventId == null || roomMemberEvent.stateKey == null || roomMemberEvent.type == null) { continue diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt index f883cc33ec6cd87e0ef3c43ccf793974e365dfb0..6306f3c6fee3b8a126d5e7cea13ae2fabbfc22c2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt @@ -35,6 +35,7 @@ import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource import org.matrix.android.sdk.internal.session.room.read.SetReadMarkersTask import org.matrix.android.sdk.internal.task.Task +import org.matrix.android.sdk.internal.util.time.Clock import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -53,7 +54,8 @@ internal class DefaultJoinRoomTask @Inject constructor( @SessionDatabase private val realmConfiguration: RealmConfiguration, private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource, - private val globalErrorReceiver: GlobalErrorReceiver + private val globalErrorReceiver: GlobalErrorReceiver, + private val clock: Clock, ) : JoinRoomTask { override suspend fun execute(params: JoinRoomTask.Params) { @@ -90,7 +92,7 @@ internal class DefaultJoinRoomTask @Inject constructor( throw JoinRoomFailure.JoinedWithTimeout } awaitTransaction(realmConfiguration) { - RoomSummaryEntity.where(it, roomId).findFirst()?.lastActivityTime = System.currentTimeMillis() + RoomSummaryEntity.where(it, roomId).findFirst()?.lastActivityTime = clock.epochMillis() } setReadMarkers(roomId) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt index 8f1aefb731efb7e70d28a8479fd2776389bb6b4a..85f53e13469ebc527500e24f6bf47dad8a8df37c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt @@ -22,7 +22,7 @@ import com.zhuinden.monarchy.Monarchy import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import org.matrix.android.sdk.api.pushrules.RuleScope +import org.matrix.android.sdk.api.session.pushrules.RuleScope import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState import org.matrix.android.sdk.api.session.room.notification.RoomPushRuleService import org.matrix.android.sdk.internal.database.model.PushRuleEntity @@ -32,7 +32,7 @@ import org.matrix.android.sdk.internal.di.SessionDatabase internal class DefaultRoomPushRuleService @AssistedInject constructor(@Assisted private val roomId: String, private val setRoomNotificationStateTask: SetRoomNotificationStateTask, @SessionDatabase private val monarchy: Monarchy) : - RoomPushRuleService { + RoomPushRuleService { @AssistedFactory interface Factory { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRule.kt index d2c0d13b5160e0a4eb7654bd921108c2a90ad35b..2c74e2a1e5d48e68ca40b03e281e8b42ef04ef77 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRule.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.session.room.notification -import org.matrix.android.sdk.api.pushrules.RuleKind -import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.RuleKind +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule internal data class RoomPushRule( val kind: RuleKind, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt index 86d2e6c619f4fbb15fa2701ad79c9bdeb0ac9fe6..a5a5ab58ba1736718094dd9e340904b1921351df 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt @@ -16,13 +16,13 @@ package org.matrix.android.sdk.internal.session.room.notification -import org.matrix.android.sdk.api.pushrules.Action -import org.matrix.android.sdk.api.pushrules.Kind -import org.matrix.android.sdk.api.pushrules.RuleSetKey -import org.matrix.android.sdk.api.pushrules.getActions -import org.matrix.android.sdk.api.pushrules.rest.PushCondition -import org.matrix.android.sdk.api.pushrules.rest.PushRule -import org.matrix.android.sdk.api.pushrules.toJson +import org.matrix.android.sdk.api.session.pushrules.Action +import org.matrix.android.sdk.api.session.pushrules.Kind +import org.matrix.android.sdk.api.session.pushrules.RuleSetKey +import org.matrix.android.sdk.api.session.pushrules.getActions +import org.matrix.android.sdk.api.session.pushrules.rest.PushCondition +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.toJson import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState import org.matrix.android.sdk.internal.database.mapper.PushRulesMapper import org.matrix.android.sdk.internal.database.model.PushRuleEntity diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/SetRoomNotificationStateTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/SetRoomNotificationStateTask.kt index feb8c27b09e332bd816122e8d3626f443833c128..021d7dbefb104ce7734f3b5fc2f2d2d83139ce91 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/SetRoomNotificationStateTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/SetRoomNotificationStateTask.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.session.room.notification import com.zhuinden.monarchy.Monarchy import io.realm.Realm -import org.matrix.android.sdk.api.pushrules.RuleScope +import org.matrix.android.sdk.api.session.pushrules.RuleScope import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState import org.matrix.android.sdk.internal.database.model.PushRuleEntity import org.matrix.android.sdk.internal.database.query.where @@ -38,7 +38,7 @@ internal interface SetRoomNotificationStateTask : Task<SetRoomNotificationStateT internal class DefaultSetRoomNotificationStateTask @Inject constructor(@SessionDatabase private val monarchy: Monarchy, private val removePushRuleTask: RemovePushRuleTask, private val addPushRuleTask: AddPushRuleTask) : - SetRoomNotificationStateTask { + SetRoomNotificationStateTask { override suspend fun execute(params: SetRoomNotificationStateTask.Params) { val currentRoomPushRule = Realm.getInstance(monarchy.realmConfiguration).use { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt index 64f1cc34f12896ac21d39c241ae93c2a142e2527..a124a8a4c2509ffe6159717b6f14d552bc98c608 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt @@ -34,6 +34,7 @@ import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHand import org.matrix.android.sdk.internal.session.sync.handler.room.RoomFullyReadHandler import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject import kotlin.collections.set @@ -58,7 +59,8 @@ internal class DefaultSetReadMarkersTask @Inject constructor( private val roomFullyReadHandler: RoomFullyReadHandler, private val readReceiptHandler: ReadReceiptHandler, @UserId private val userId: String, - private val globalErrorReceiver: GlobalErrorReceiver + private val globalErrorReceiver: GlobalErrorReceiver, + private val clock: Clock, ) : SetReadMarkersTask { override suspend fun execute(params: SetReadMarkersTask.Params) { @@ -125,7 +127,7 @@ internal class DefaultSetReadMarkersTask @Inject constructor( roomFullyReadHandler.handle(realm, roomId, FullyReadContent(readMarkerId)) } if (readReceiptId != null) { - val readReceiptContent = ReadReceiptHandler.createContent(userId, readReceiptId) + val readReceiptContent = ReadReceiptHandler.createContent(userId, readReceiptId, clock.epochMillis()) readReceiptHandler.handle(realm, roomId, readReceiptContent, false, null) } if (shouldUpdateRoomSummary) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/EventEditor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/EventEditor.kt index b54cd71e5082a612ec115b1dd43057e6c45ee834..7bf7d6b587584285cdfc697337b9730c7f424377 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/EventEditor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/EventEditor.kt @@ -27,12 +27,16 @@ import org.matrix.android.sdk.internal.database.mapper.toEntity import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject -internal class EventEditor @Inject constructor(private val eventSenderProcessor: EventSenderProcessor, - private val eventFactory: LocalEchoEventFactory, - private val localEchoRepository: LocalEchoRepository) { +internal class EventEditor @Inject constructor( + private val eventSenderProcessor: EventSenderProcessor, + private val eventFactory: LocalEchoEventFactory, + private val localEchoRepository: LocalEchoRepository, + private val clock: Clock, +) { fun editTextMessage(targetEvent: TimelineEvent, msgType: String, @@ -126,7 +130,7 @@ internal class EventEditor @Inject constructor(private val eventSenderProcessor: } private fun updateFailedEchoWithEvent(roomId: String, failedEchoEventId: String, editedEvent: Event) { - val editedEventEntity = editedEvent.toEntity(roomId, SendState.UNSENT, System.currentTimeMillis()) + val editedEventEntity = editedEvent.toEntity(roomId, SendState.UNSENT, clock.epochMillis()) localEchoRepository.updateEchoAsync(failedEchoEventId) { _, entity -> entity.content = editedEventEntity.content entity.ageLocalTs = editedEventEntity.ageLocalTs diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadSummariesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadSummariesTask.kt index b596f2288ec82f849ca708b5a0a7225ea83cff78..c5f9bd13fd59b889ea18b5e2ab6597a63a22d6df 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadSummariesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadSummariesTask.kt @@ -33,6 +33,7 @@ import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection import org.matrix.android.sdk.internal.session.room.timeline.PaginationResponse import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject @@ -55,12 +56,14 @@ internal class DefaultFetchThreadSummariesTask @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val cryptoService: DefaultCryptoService, @UserId private val userId: String, + private val clock: Clock, ) : FetchThreadSummariesTask { override suspend fun execute(params: FetchThreadSummariesTask.Params): Result { val filter = FilterFactory.createThreadsFilter( numberOfEvents = params.limit, - userId = if (params.isUserParticipating) userId else null).toJSONString() + userId = if (params.isUserParticipating) userId else null + ).toJSONString() val response = executeRequest( globalErrorReceiver, @@ -94,7 +97,9 @@ internal class DefaultFetchThreadSummariesTask @Inject constructor( roomMemberContentsByUser = roomMemberContentsByUser, roomEntity = roomEntity, userId = userId, - cryptoService = cryptoService) + cryptoService = cryptoService, + currentTimeMillis = clock.epochMillis(), + ) } } return Result.SUCCESS diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt index 116d4aa0a1ab5f427fe0e1e8737e8b13a8cdb633..8d35a8fea4cb4fec267ee82051fa85baa78d9f33 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt @@ -23,7 +23,6 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.send.SendState -import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider import org.matrix.android.sdk.internal.crypto.DefaultCryptoService import org.matrix.android.sdk.internal.database.helper.addTimelineEvent import org.matrix.android.sdk.internal.database.mapper.asDomain @@ -42,7 +41,6 @@ import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.database.query.getOrNull import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase -import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.events.getFixedRoomMemberContent @@ -51,6 +49,7 @@ import org.matrix.android.sdk.internal.session.room.relation.RelationsResponse import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject @@ -85,10 +84,9 @@ internal interface FetchThreadTimelineTask : Task<FetchThreadTimelineTask.Params internal class DefaultFetchThreadTimelineTask @Inject constructor( private val roomAPI: RoomAPI, private val globalErrorReceiver: GlobalErrorReceiver, - private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, @SessionDatabase private val monarchy: Monarchy, - @UserId private val userId: String, - private val cryptoService: DefaultCryptoService + private val cryptoService: DefaultCryptoService, + private val clock: Clock, ) : FetchThreadTimelineTask { enum class Result { @@ -156,7 +154,8 @@ internal class DefaultFetchThreadTimelineTask @Inject constructor( eventEntity = eventEntity, direction = PaginationDirection.FORWARDS, ownedByThreadChunk = true, - roomMemberContentsByUser = roomMemberContentsByUser) + roomMemberContentsByUser = roomMemberContentsByUser + ) } } @@ -178,7 +177,8 @@ internal class DefaultFetchThreadTimelineTask @Inject constructor( eventEntity = eventEntity, direction = PaginationDirection.FORWARDS, ownedByThreadChunk = true, - roomMemberContentsByUser = roomMemberContentsByUser) + roomMemberContentsByUser = roomMemberContentsByUser + ) } } } @@ -207,7 +207,7 @@ internal class DefaultFetchThreadTimelineTask @Inject constructor( * Create an EventEntity to be added in the TimelineEventEntity */ private fun createEventEntity(roomId: String, event: Event, realm: Realm): EventEntity { - val ageLocalTs = event.unsignedData?.age?.let { System.currentTimeMillis() - it } + val ageLocalTs = event.unsignedData?.age?.let { clock.epochMillis() - it } return event.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt index bb16563f96ac622d8ca9057040d30d5de4d2517e..d019ffada62a2a6815b13eb72014314b746fe25a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt @@ -37,13 +37,13 @@ import org.matrix.android.sdk.api.session.room.model.message.LocationAsset import org.matrix.android.sdk.api.session.room.model.message.LocationAssetType import org.matrix.android.sdk.api.session.room.model.message.LocationInfo import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent import org.matrix.android.sdk.api.session.room.model.message.MessageFormat import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent -import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent @@ -70,8 +70,8 @@ import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.content.ThumbnailExtractor import org.matrix.android.sdk.internal.session.permalinks.PermalinkFactory import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils +import org.matrix.android.sdk.internal.util.time.Clock import java.util.UUID -import java.util.concurrent.TimeUnit import javax.inject.Inject /** @@ -91,7 +91,8 @@ internal class LocalEchoEventFactory @Inject constructor( private val thumbnailExtractor: ThumbnailExtractor, private val waveformSanitizer: WaveFormSanitizer, private val localEchoRepository: LocalEchoRepository, - private val permalinkFactory: PermalinkFactory + private val permalinkFactory: PermalinkFactory, + private val clock: Clock, ) { fun createTextEvent(roomId: String, msgType: String, text: CharSequence, autoMarkdown: Boolean): Event { if (msgType == MessageType.MSGTYPE_TEXT || msgType == MessageType.MSGTYPE_EMOTE) { @@ -124,7 +125,8 @@ internal class LocalEchoEventFactory @Inject constructor( newBodyAutoMarkdown: Boolean, msgType: String, compatibilityText: String): Event { - return createMessageEvent(roomId, + return createMessageEvent( + roomId, MessageTextContent( msgType = msgType, body = compatibilityText, @@ -132,7 +134,8 @@ internal class LocalEchoEventFactory @Inject constructor( newContent = createTextContent(newBodyText, newBodyAutoMarkdown) .toMessageTextContent(msgType) .toContent() - )) + ) + ) } private fun createPollContent(question: String, @@ -188,7 +191,8 @@ internal class LocalEchoEventFactory @Inject constructor( eventId = localId, type = EventType.POLL_RESPONSE.first(), content = content.toContent(), - unsignedData = UnsignedData(age = null, transactionId = localId)) + unsignedData = UnsignedData(age = null, transactionId = localId) + ) } fun createPollEvent(roomId: String, @@ -204,7 +208,8 @@ internal class LocalEchoEventFactory @Inject constructor( eventId = localId, type = EventType.POLL_START.first(), content = content.toContent(), - unsignedData = UnsignedData(age = null, transactionId = localId)) + unsignedData = UnsignedData(age = null, transactionId = localId) + ) } fun createEndPollEvent(roomId: String, @@ -223,7 +228,8 @@ internal class LocalEchoEventFactory @Inject constructor( eventId = localId, type = EventType.POLL_END.first(), content = content.toContent(), - unsignedData = UnsignedData(age = null, transactionId = localId)) + unsignedData = UnsignedData(age = null, transactionId = localId) + ) } fun createLocationEvent(roomId: String, @@ -238,7 +244,7 @@ internal class LocalEchoEventFactory @Inject constructor( body = geoUri, unstableLocationInfo = LocationInfo(geoUri = geoUri, description = geoUri), unstableLocationAsset = LocationAsset(type = assetType), - unstableTs = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), + unstableTimestampMillis = clock.epochMillis(), unstableText = geoUri ) return createMessageEvent(roomId, content) @@ -250,14 +256,14 @@ internal class LocalEchoEventFactory @Inject constructor( longitude: Double, uncertainty: Double?): Event { val geoUri = buildGeoUri(latitude, longitude, uncertainty) - val content = MessageLiveLocationContent( + val content = MessageBeaconLocationDataContent( body = geoUri, relatesTo = RelationDefaultContent( type = RelationType.REFERENCE, eventId = beaconInfoEventId ), unstableLocationInfo = LocationInfo(geoUri = geoUri, description = geoUri), - unstableTimestampAsMilliseconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), + unstableTimestampMillis = clock.epochMillis(), ) val localId = LocalEcho.createLocalEchoId() return Event( @@ -267,7 +273,8 @@ internal class LocalEchoEventFactory @Inject constructor( eventId = localId, type = EventType.BEACON_LOCATION_DATA.first(), content = content.toContent(), - unsignedData = UnsignedData(age = null, transactionId = localId)) + unsignedData = UnsignedData(age = null, transactionId = localId) + ) } fun createReplaceTextOfReply(roomId: String, @@ -297,7 +304,8 @@ internal class LocalEchoEventFactory @Inject constructor( // val replyFallback = buildReplyFallback(body, originalEvent.root.senderId ?: "", newBodyText) - return createMessageEvent(roomId, + return createMessageEvent( + roomId, MessageTextContent( msgType = msgType, body = compatibilityText, @@ -309,7 +317,8 @@ internal class LocalEchoEventFactory @Inject constructor( formattedBody = replyFormatted ) .toContent() - )) + ) + ) } fun createMediaEvent(roomId: String, @@ -341,7 +350,8 @@ internal class LocalEchoEventFactory @Inject constructor( eventId = localId, type = EventType.REACTION, content = content.toContent(), - unsignedData = UnsignedData(age = null, transactionId = localId)) + unsignedData = UnsignedData(age = null, transactionId = localId) + ) } private fun createImageEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?): Event { @@ -532,12 +542,14 @@ internal class LocalEchoEventFactory @Inject constructor( content.toThreadTextContent( rootThreadEventId = rootThreadEventId, latestThreadEventId = localEchoRepository.getLatestThreadEvent(rootThreadEventId), - msgType = msgType) - .toContent()) + msgType = msgType + ) + .toContent() + ) } private fun dummyOriginServerTs(): Long { - return System.currentTimeMillis() + return clock.epochMillis() } /** @@ -582,7 +594,9 @@ internal class LocalEchoEventFactory @Inject constructor( relatesTo = generateReplyRelationContent( eventId = eventId, rootThreadEventId = rootThreadEventId, - showInThread = showInThread)) + showInThread = showInThread + ) + ) return createMessageEvent(roomId, content) } @@ -605,7 +619,8 @@ internal class LocalEchoEventFactory @Inject constructor( eventId = it, isFallingBack = showInThread, // False when is a rich reply from within a thread, and true when is a reply that should be visible from threads - inReplyTo = ReplyToContent(eventId = eventId)) + inReplyTo = ReplyToContent(eventId = eventId) + ) } ?: RelationDefaultContent(null, null, ReplyToContent(eventId = eventId)) private fun buildFormattedReply(permalink: String, userLink: String, userId: String, bodyFormatted: String, newBodyFormatted: String): String { @@ -740,13 +755,15 @@ internal class LocalEchoEventFactory @Inject constructor( .toThreadTextContent( rootThreadEventId = rootThreadEventId, latestThreadEventId = localEchoRepository.getLatestThreadEvent(rootThreadEventId), - msgType = MessageType.MSGTYPE_TEXT) + msgType = MessageType.MSGTYPE_TEXT + ) ) } else { createFormattedTextEvent( roomId, markdownParser.parse(quoteText, force = true, advanced = autoMarkdown), - MessageType.MSGTYPE_TEXT) + MessageType.MSGTYPE_TEXT + ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt index 1b1a66a1c418acae50f4e109b1403346e1e76cbf..9fd45b917fa28f3a0df38abb6994f57de30c4043 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt @@ -43,16 +43,20 @@ import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater import org.matrix.android.sdk.internal.session.room.timeline.TimelineInput import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.util.awaitTransaction +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import java.util.UUID import javax.inject.Inject -internal class LocalEchoRepository @Inject constructor(@SessionDatabase private val monarchy: Monarchy, - private val taskExecutor: TaskExecutor, - private val realmSessionProvider: RealmSessionProvider, - private val roomSummaryUpdater: RoomSummaryUpdater, - private val timelineInput: TimelineInput, - private val timelineEventMapper: TimelineEventMapper) { +internal class LocalEchoRepository @Inject constructor( + @SessionDatabase private val monarchy: Monarchy, + private val taskExecutor: TaskExecutor, + private val realmSessionProvider: RealmSessionProvider, + private val roomSummaryUpdater: RoomSummaryUpdater, + private val timelineInput: TimelineInput, + private val timelineEventMapper: TimelineEventMapper, + private val clock: Clock, +) { fun createLocalEcho(event: Event) { val roomId = event.roomId ?: throw IllegalStateException("You should have set a roomId for your event") @@ -61,7 +65,7 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private event.type ?: throw IllegalStateException("You should have set a type for your event") val timelineEventEntity = realmSessionProvider.withRealm { realm -> - val eventEntity = event.toEntity(roomId, SendState.UNSENT, System.currentTimeMillis()) + val eventEntity = event.toEntity(roomId, SendState.UNSENT, clock.epochMillis()) val roomMemberHelper = RoomMemberHelper(realm, roomId) val myUser = roomMemberHelper.getLastRoomMember(senderId) val localId = UUID.randomUUID().mostSignificantBits @@ -88,7 +92,7 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private } fun updateSendState(eventId: String, roomId: String?, sendState: SendState, sendStateDetails: String? = null) { - Timber.v("## SendEvent: [${System.currentTimeMillis()}] Update local state of $eventId to ${sendState.name}") + Timber.v("## SendEvent: [${clock.epochMillis()}] Update local state of $eventId to ${sendState.name}") timelineInput.onLocalEchoUpdated(roomId = roomId ?: "", eventId = eventId, sendState = sendState) updateEchoAsync(eventId) { realm, sendingEventEntity -> if (sendState == SendState.SENT && sendingEventEntity.sendState == SendState.SYNCED) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt index b59f1b174f2d16f7a321834aac1b0566bd1c10d3..ecc81492554838d1fdbebb1757003db4bc65dce3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt @@ -39,7 +39,7 @@ import javax.inject.Inject * Possible next worker : None, but it will post new work to send events, encrypted or not */ internal class MultipleEventSendingDispatcherWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<MultipleEventSendingDispatcherWorker.Params>(context, params, sessionManager, Params::class.java) { + SessionSafeCoroutineWorker<MultipleEventSendingDispatcherWorker.Params>(context, params, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( @@ -76,10 +76,10 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo params.localEchoIds.forEach { localEchoIds -> val roomId = localEchoIds.roomId val eventId = localEchoIds.eventId - localEchoRepository.updateSendState(eventId, roomId, SendState.SENDING) - Timber.v("## SendEvent: [${System.currentTimeMillis()}] Schedule send event $eventId") - val sendWork = createSendEventWork(params.sessionId, eventId, true) - timelineSendEventWorkCommon.postWork(roomId, sendWork) + localEchoRepository.updateSendState(eventId, roomId, SendState.SENDING) + Timber.v("## SendEvent: Schedule send event $eventId") + val sendWork = createSendEventWork(params.sessionId, eventId, true) + timelineSendEventWorkCommon.postWork(roomId, sendWork) } return Result.success() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt index c03d1fa81e1dba968ad255ad852d6ffc63721290..83c61d28451b3718b190264df985d659e0c5bda7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt @@ -34,7 +34,7 @@ import javax.inject.Inject * Possible next worker : None */ internal class RedactEventWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<RedactEventWorker.Params>(context, params, sessionManager, Params::class.java) { + SessionSafeCoroutineWorker<RedactEventWorker.Params>(context, params, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt index 7f24688ecea1cb17d3570cfd900c8dee9426883d..ddbe8a61a0f0ef4a45a52933a2a5c8e9a41f824f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt @@ -40,7 +40,7 @@ import javax.inject.Inject * Possible next worker : None */ internal class SendEventWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<SendEventWorker.Params>(context, params, sessionManager, Params::class.java) { + SessionSafeCoroutineWorker<SendEventWorker.Params>(context, params, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( @@ -89,13 +89,13 @@ internal class SendEventWorker(context: Context, params: WorkerParameters, sessi .also { Timber.e("Work cancelled due to input error from parent") } } - Timber.v("## SendEvent: [${System.currentTimeMillis()}] Send event ${params.eventId}") + Timber.v("## SendEvent: Send event ${params.eventId}") return try { sendEventTask.execute(SendEventTask.Params(event, params.isEncrypted ?: cryptoService.isRoomEncrypted(event.roomId))) Result.success() } catch (exception: Throwable) { if (/*currentAttemptCount >= MAX_NUMBER_OF_RETRY_BEFORE_FAILING ||**/ !exception.shouldBeRetried()) { - Timber.e("## SendEvent: [${System.currentTimeMillis()}] Send event Failed cannot retry ${params.eventId} > ${exception.localizedMessage}") + Timber.e("## SendEvent: Send event Failed cannot retry ${params.eventId} > ${exception.localizedMessage}") localEchoRepository.updateSendState( eventId = event.eventId, roomId = event.roomId, @@ -104,7 +104,7 @@ internal class SendEventWorker(context: Context, params: WorkerParameters, sessi ) Result.success() } else { - Timber.e("## SendEvent: [${System.currentTimeMillis()}] Send event Failed schedule retry ${params.eventId} > ${exception.localizedMessage}") + Timber.e("## SendEvent: Send event Failed schedule retry ${params.eventId} > ${exception.localizedMessage}") Result.retry() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt index 5b4efa5df6fdf26ccfaddb7ff145043cafc26d7a..a1d3e2c0ac45ea670c85a38cf2f065e6c464cb24 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt @@ -191,7 +191,7 @@ internal class EventSenderProcessorCoroutine @Inject constructor( private suspend fun QueuedTask.waitForNetwork() = waitForNetworkSequencer.post { while (!canReachServer.get()) { - Timber.v("## $this cannot reach server wait ts:${System.currentTimeMillis()}") + Timber.v("## $this cannot reach server wait for $$RETRY_WAIT_TIME_MS ms") delay(RETRY_WAIT_TIME_MS) withContext(Dispatchers.IO) { val hostAvailable = HomeServerAvailabilityChecker(sessionParams).check() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt index 1ee313919401fcd72917d9d14ba048ad9bd71132..301f8cb9d67f811840fd98977e1a585894063d15 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt @@ -136,7 +136,7 @@ internal class EventSenderProcessorThread @Inject constructor( private var retryNoNetworkTask: TimerTask? = null override fun run() { - Timber.v("## SendThread started ts:${System.currentTimeMillis()}") + Timber.v("## SendThread started") try { while (!isInterrupted) { Timber.v("## SendThread wait for task to process") @@ -151,7 +151,7 @@ internal class EventSenderProcessorThread @Inject constructor( } // we check for network connectivity while (!canReachServer) { - Timber.v("## SendThread cannot reach server, wait ts:${System.currentTimeMillis()}") + Timber.v("## SendThread cannot reach server") // schedule to retry waitForNetwork() // if thread as been killed meanwhile @@ -175,7 +175,7 @@ internal class EventSenderProcessorThread @Inject constructor( canReachServer = false if (task.retryCount.getAndIncrement() >= 3) task.onTaskFailed() while (!canReachServer) { - Timber.v("## SendThread retryLoop cannot reach server, wait ts:${System.currentTimeMillis()}") + Timber.v("## SendThread retryLoop cannot reach server") // schedule to retry waitForNetwork() } @@ -218,7 +218,7 @@ internal class EventSenderProcessorThread @Inject constructor( // state = State.KILLED // is this needed? retryNoNetworkTask?.cancel() - Timber.w("## SendThread finished ${System.currentTimeMillis()}") + Timber.w("## SendThread finished") } private fun waitForNetwork() { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueueMemento.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueueMemento.kt index 116c8d5c6b6c8a0ddf6e2ffff9b2e02c09c7e019..545fc4173729fa91381a99c4faac96a0b091e254 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueueMemento.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueueMemento.kt @@ -74,7 +74,7 @@ internal class QueueMemento @Inject constructor(context: Context, encrypt = task.encrypt, order = order ) - is RedactQueuedTask -> RedactEventTaskInfo( + is RedactQueuedTask -> RedactEventTaskInfo( redactionLocalEcho = task.redactionLocalEchoId, order = order ) @@ -92,7 +92,7 @@ internal class QueueMemento @Inject constructor(context: Context, ?.forEach { info -> try { when (info) { - is SendEventTaskInfo -> { + is SendEventTaskInfo -> { localEchoRepository.getUpToDateEcho(info.localEchoId)?.let { if (it.sendState.isSending() && it.eventId != null && it.roomId != null) { localEchoRepository.updateSendState(it.eventId, it.roomId, SendState.UNSENT) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt index 89d33f98d219a7d054d578e61bc9db4586064d11..e5c7a75cb6bd19e7ccf66e171344c91bc059972d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt @@ -33,8 +33,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent -import org.matrix.android.sdk.api.session.room.model.livelocation.BeaconInfo -import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationBeaconContent +import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent import org.matrix.android.sdk.api.session.room.state.StateService import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.MimeTypes @@ -74,14 +73,14 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private eventType: String, stateKey: String, body: JsonDict - ) { + ): String { val params = SendStateTask.Params( roomId = roomId, stateKey = stateKey, eventType = eventType, body = body.toSafeJson(eventType) ) - sendStateTask.executeRetry(params, 3) + return sendStateTask.executeRetry(params, 3) } private fun JsonDict.toSafeJson(eventType: String): JsonDict { @@ -193,20 +192,13 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private override suspend fun stopLiveLocation(userId: String) { getLiveLocationBeaconInfo(userId, true)?.let { beaconInfoStateEvent -> - beaconInfoStateEvent.getClearContent()?.toModel<LiveLocationBeaconContent>()?.let { content -> - val beaconContent = LiveLocationBeaconContent( - unstableBeaconInfo = BeaconInfo( - description = content.getBestBeaconInfo()?.description, - timeout = content.getBestBeaconInfo()?.timeout, - isLive = false, - ), - unstableTimestampAsMilliseconds = System.currentTimeMillis() - ).toContent() + beaconInfoStateEvent.getClearContent()?.toModel<MessageBeaconInfoContent>()?.let { content -> + val updatedContent = content.copy(isLive = false).toContent() beaconInfoStateEvent.stateKey?.let { sendStateEvent( eventType = EventType.STATE_ROOM_BEACON_INFO.first(), - body = beaconContent, + body = updatedContent, stateKey = it ) } @@ -225,7 +217,7 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private } .firstOrNull { beaconInfoEvent -> !filterOnlyLive || - beaconInfoEvent.getClearContent()?.toModel<LiveLocationBeaconContent>()?.getBestBeaconInfo()?.isLive.orFalse() + beaconInfoEvent.getClearContent()?.toModel<MessageBeaconInfoContent>()?.isLive.orFalse() } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt index 197b4f8688c7d38cf244785b21bb39d96bd40df3..1f2ec09367d4c996c70445b6dab0a27bf9ff3181 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SafePowerLevelContent.kt @@ -51,7 +51,7 @@ internal fun JsonDict.toSafePowerLevelsContentDict(): JsonDict { usersDefault = content.usersDefault, users = content.users, stateDefault = content.stateDefault, - notifications = content.notifications?.mapValues { content.notificationLevel(it.key) } + notifications = content.notifications?.mapValues { content.notificationLevel(it.key) } ) } ?.toContent() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt index 56c69a05a682e7cbcb89763d586ed4317d15be55..59c9de29328b6d634bbcebc7552e8f477001737d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt @@ -21,9 +21,10 @@ import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task +import timber.log.Timber import javax.inject.Inject -internal interface SendStateTask : Task<SendStateTask.Params, Unit> { +internal interface SendStateTask : Task<SendStateTask.Params, String> { data class Params( val roomId: String, val stateKey: String, @@ -37,9 +38,9 @@ internal class DefaultSendStateTask @Inject constructor( private val globalErrorReceiver: GlobalErrorReceiver ) : SendStateTask { - override suspend fun execute(params: SendStateTask.Params) { + override suspend fun execute(params: SendStateTask.Params): String { return executeRequest(globalErrorReceiver) { - if (params.stateKey.isEmpty()) { + val response = if (params.stateKey.isEmpty()) { roomAPI.sendStateEvent( roomId = params.roomId, stateEventType = params.eventType, @@ -53,6 +54,9 @@ internal class DefaultSendStateTask @Inject constructor( params = params.body ) } + response.eventId.also { + Timber.d("State event: $it just sent in room ${params.roomId}") + } } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt index e3a215445db74897fe080aa22a32d705d8edb7a5..52879d71219264e422502d08e3dab0f163e54566 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt @@ -101,11 +101,11 @@ internal class Graph { // it's a candidate destination = it.destination } - inPath -> { + inPath -> { // Cycle!! backwardEdges.add(it) } - completed -> { + completed -> { // dead end } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt index 18a4f80547cb23e23914a686d466b8967bd0994c..96e8d3c73f451c8ea1fa2c412258df8710ff3a83 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt @@ -26,7 +26,6 @@ import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmQuery import io.realm.kotlin.where -import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.query.ActiveSpaceFilter import org.matrix.android.sdk.api.query.RoomCategoryFilter import org.matrix.android.sdk.api.query.isNormalized @@ -43,7 +42,6 @@ import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotification import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional -import org.matrix.android.sdk.internal.database.RealmSessionProvider import org.matrix.android.sdk.internal.database.mapper.RoomSummaryMapper import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields @@ -57,10 +55,8 @@ import javax.inject.Inject internal class RoomSummaryDataSource @Inject constructor( @SessionDatabase private val monarchy: Monarchy, - private val realmSessionProvider: RealmSessionProvider, private val roomSummaryMapper: RoomSummaryMapper, private val queryStringValueProcessor: QueryStringValueProcessor, - private val coroutineDispatchers: MatrixCoroutineDispatchers ) { fun getRoomSummary(roomIdOrAlias: String): RoomSummary? { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt index 5064ebf49b3d36696726277fef5c5a95309f5ca3..18fbe73c098e58b831eed28eb4caacd2df24e9e9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt @@ -43,28 +43,32 @@ import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHand import org.matrix.android.sdk.internal.session.sync.handler.room.ThreadsAwarenessHandler import org.matrix.android.sdk.internal.task.SemaphoreCoroutineSequencer import org.matrix.android.sdk.internal.util.createBackgroundHandler +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import java.util.UUID import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicReference -internal class DefaultTimeline(private val roomId: String, - private val initialEventId: String?, - private val realmConfiguration: RealmConfiguration, - private val loadRoomMembersTask: LoadRoomMembersTask, - private val readReceiptHandler: ReadReceiptHandler, - private val settings: TimelineSettings, - private val coroutineDispatchers: MatrixCoroutineDispatchers, - paginationTask: PaginationTask, - getEventTask: GetContextOfEventTask, - fetchTokenAndPaginateTask: FetchTokenAndPaginateTask, - fetchThreadTimelineTask: FetchThreadTimelineTask, - timelineEventMapper: TimelineEventMapper, - timelineInput: TimelineInput, - threadsAwarenessHandler: ThreadsAwarenessHandler, - lightweightSettingsStorage: LightweightSettingsStorage, - eventDecryptor: TimelineEventDecryptor) : Timeline { +internal class DefaultTimeline( + private val roomId: String, + private val initialEventId: String?, + private val realmConfiguration: RealmConfiguration, + private val loadRoomMembersTask: LoadRoomMembersTask, + private val readReceiptHandler: ReadReceiptHandler, + private val settings: TimelineSettings, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val clock: Clock, + paginationTask: PaginationTask, + getEventTask: GetContextOfEventTask, + fetchTokenAndPaginateTask: FetchTokenAndPaginateTask, + fetchThreadTimelineTask: FetchThreadTimelineTask, + timelineEventMapper: TimelineEventMapper, + timelineInput: TimelineInput, + threadsAwarenessHandler: ThreadsAwarenessHandler, + lightweightSettingsStorage: LightweightSettingsStorage, + eventDecryptor: TimelineEventDecryptor, +) : Timeline { companion object { val BACKGROUND_HANDLER = createBackgroundHandler("DefaultTimeline_Thread") @@ -100,6 +104,7 @@ internal class DefaultTimeline(private val roomId: String, threadsAwarenessHandler = threadsAwarenessHandler, lightweightSettingsStorage = lightweightSettingsStorage, onEventsUpdated = this::sendSignalToPostSnapshot, + onEventsDeleted = this::onEventsDeleted, onLimitedTimeline = this::onLimitedTimeline, onNewTimelineEvents = this::onNewTimelineEvents ) @@ -304,6 +309,12 @@ internal class DefaultTimeline(private val roomId: String, } } + private fun onEventsDeleted() { + // Some event have been deleted, for instance when a user has been ignored. + // Restart the timeline (live) + restartWithEventId(null) + } + private suspend fun postSnapshot() { val snapshot = strategy.buildSnapshot() Timber.v("Post snapshot of ${snapshot.size} events") @@ -363,7 +374,8 @@ internal class DefaultTimeline(private val roomId: String, roomId = roomId, timelineId = timelineID, mode = mode, - dependencies = strategyDependencies + dependencies = strategyDependencies, + clock = clock, ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt index 826c9d7c48ef60800c13cdd3db5e355ba61d557d..849d7bd7ab6b195b244b3173dbec48a4a5757620 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt @@ -34,6 +34,7 @@ import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTa import org.matrix.android.sdk.internal.session.room.relation.threads.FetchThreadTimelineTask import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHandler import org.matrix.android.sdk.internal.session.sync.handler.room.ThreadsAwarenessHandler +import org.matrix.android.sdk.internal.util.time.Clock internal class DefaultTimelineService @AssistedInject constructor( @Assisted private val roomId: String, @@ -50,8 +51,9 @@ internal class DefaultTimelineService @AssistedInject constructor( private val lightweightSettingsStorage: LightweightSettingsStorage, private val readReceiptHandler: ReadReceiptHandler, private val coroutineDispatchers: MatrixCoroutineDispatchers, - private val timelineEventDataSource: TimelineEventDataSource -) : TimelineService { + private val timelineEventDataSource: TimelineEventDataSource, + private val clock: Clock, + ) : TimelineService { @AssistedFactory interface Factory { @@ -75,7 +77,8 @@ internal class DefaultTimelineService @AssistedInject constructor( readReceiptHandler = readReceiptHandler, getEventTask = contextOfEventTask, threadsAwarenessHandler = threadsAwarenessHandler, - lightweightSettingsStorage = lightweightSettingsStorage + lightweightSettingsStorage = lightweightSettingsStorage, + clock = clock ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt index 5bca5118b82e20478569e6a7500348a37ee4f28b..aef9e24c8b912d7a80dc02a082a55fe81c839a35 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt @@ -24,6 +24,7 @@ import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task +import org.matrix.android.sdk.internal.util.time.Clock import javax.inject.Inject internal interface GetEventTask : Task<GetEventTask.Params, Event> { @@ -36,7 +37,8 @@ internal interface GetEventTask : Task<GetEventTask.Params, Event> { internal class DefaultGetEventTask @Inject constructor( private val roomAPI: RoomAPI, private val globalErrorReceiver: GlobalErrorReceiver, - private val eventDecryptor: EventDecryptor + private val eventDecryptor: EventDecryptor, + private val clock: Clock, ) : GetEventTask { override suspend fun execute(params: GetEventTask.Params): Event { @@ -59,7 +61,7 @@ internal class DefaultGetEventTask @Inject constructor( } } - event.ageLocalTs = event.unsignedData?.age?.let { System.currentTimeMillis() - it } + event.ageLocalTs = event.unsignedData?.age?.let { clock.epochMillis() - it } return event } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LiveTimelineEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LiveTimelineEvent.kt index 64b1a4ff1d5df72056367b388f826eb90df2776f..e765e05578833c577c1fdcc9955318307ca04704 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LiveTimelineEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LiveTimelineEvent.kt @@ -41,7 +41,7 @@ internal class LiveTimelineEvent(private val monarchy: Monarchy, private val timelineEventMapper: TimelineEventMapper, private val roomId: String, private val eventId: String) : - MediatorLiveData<Optional<TimelineEvent>>() { + MediatorLiveData<Optional<TimelineEvent>>() { init { buildAndObserveQuery() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt index ff986d04af15e43262112340518d49bff5c76c6d..bcf202962c9399a88c8d51b14948137e555c5e31 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt @@ -42,6 +42,7 @@ import org.matrix.android.sdk.internal.database.query.findLastForwardChunkOfThre import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.session.room.relation.threads.FetchThreadTimelineTask import org.matrix.android.sdk.internal.session.sync.handler.room.ThreadsAwarenessHandler +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import java.util.concurrent.atomic.AtomicReference @@ -53,11 +54,13 @@ import java.util.concurrent.atomic.AtomicReference * Once we got a ChunkEntity we wrap it with TimelineChunk class so we dispatch any methods for loading data. */ -internal class LoadTimelineStrategy( +internal class LoadTimelineStrategy constructor( private val roomId: String, private val timelineId: String, private val mode: Mode, - private val dependencies: Dependencies) { + private val dependencies: Dependencies, + clock: Clock, +) { sealed interface Mode { object Live : Mode @@ -95,6 +98,7 @@ internal class LoadTimelineStrategy( val threadsAwarenessHandler: ThreadsAwarenessHandler, val lightweightSettingsStorage: LightweightSettingsStorage, val onEventsUpdated: (Boolean) -> Unit, + val onEventsDeleted: () -> Unit, val onLimitedTimeline: () -> Unit, val onNewTimelineEvents: (List<String>) -> Unit ) @@ -152,7 +156,7 @@ internal class LoadTimelineStrategy( } } - private val uiEchoManager = UIEchoManager(uiEchoManagerListener) + private val uiEchoManager = UIEchoManager(uiEchoManagerListener, clock) private val sendingEventsDataSource: SendingEventsDataSource = RealmSendingEventsDataSource( roomId = roomId, realm = dependencies.realm, @@ -302,7 +306,8 @@ internal class LoadTimelineStrategy( threadsAwarenessHandler = dependencies.threadsAwarenessHandler, lightweightSettingsStorage = dependencies.lightweightSettingsStorage, initialEventId = mode.originEventId(), - onBuiltEvents = dependencies.onEventsUpdated + onBuiltEvents = dependencies.onEventsUpdated, + onEventsDeleted = dependencies.onEventsDeleted, ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt index 4ead1d4ecba2805ca9e9622fd7dffdd1254b6cf0..27f4245b22803d070865454db93e5478247bab35 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt @@ -49,21 +49,24 @@ import java.util.concurrent.atomic.AtomicBoolean * It does mainly listen to the db timeline events. * It also triggers pagination to the server when needed, or dispatch to the prev or next chunk if any. */ -internal class TimelineChunk(private val chunkEntity: ChunkEntity, - private val timelineSettings: TimelineSettings, - private val roomId: String, - private val timelineId: String, - private val fetchThreadTimelineTask: FetchThreadTimelineTask, - private val eventDecryptor: TimelineEventDecryptor, - private val paginationTask: PaginationTask, - private val realmConfiguration: RealmConfiguration, - private val fetchTokenAndPaginateTask: FetchTokenAndPaginateTask, - private val timelineEventMapper: TimelineEventMapper, - private val uiEchoManager: UIEchoManager? = null, - private val threadsAwarenessHandler: ThreadsAwarenessHandler, - private val lightweightSettingsStorage: LightweightSettingsStorage, - private val initialEventId: String?, - private val onBuiltEvents: (Boolean) -> Unit) { +internal class TimelineChunk( + private val chunkEntity: ChunkEntity, + private val timelineSettings: TimelineSettings, + private val roomId: String, + private val timelineId: String, + private val fetchThreadTimelineTask: FetchThreadTimelineTask, + private val eventDecryptor: TimelineEventDecryptor, + private val paginationTask: PaginationTask, + private val realmConfiguration: RealmConfiguration, + private val fetchTokenAndPaginateTask: FetchTokenAndPaginateTask, + private val timelineEventMapper: TimelineEventMapper, + private val uiEchoManager: UIEchoManager?, + private val threadsAwarenessHandler: ThreadsAwarenessHandler, + private val lightweightSettingsStorage: LightweightSettingsStorage, + private val initialEventId: String?, + private val onBuiltEvents: (Boolean) -> Unit, + private val onEventsDeleted: () -> Unit, +) { private val isLastForward = AtomicBoolean(chunkEntity.isLastForward) private val isLastBackward = AtomicBoolean(chunkEntity.isLastBackward) @@ -505,6 +508,11 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity, if (insertions.isNotEmpty() || modifications.isNotEmpty()) { onBuiltEvents(true) } + + val deletions = changeSet.deletions + if (deletions.isNotEmpty()) { + onEventsDeleted() + } } private fun getNextDisplayIndex(direction: Timeline.Direction): Int? { @@ -543,7 +551,8 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity, threadsAwarenessHandler = threadsAwarenessHandler, lightweightSettingsStorage = lightweightSettingsStorage, initialEventId = null, - onBuiltEvents = this.onBuiltEvents + onBuiltEvents = this.onBuiltEvents, + onEventsDeleted = this.onEventsDeleted ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDataSource.kt index 638866a46efbf7865c45387301dbc5dc1fd7efec..8b58d3ca5c111064da10d2b813a68e80724b2a24 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDataSource.kt @@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.session.room.timeline import androidx.lifecycle.LiveData import com.zhuinden.monarchy.Monarchy import io.realm.Sort -import io.realm.kotlin.where import org.matrix.android.sdk.api.session.events.model.isImageMessage import org.matrix.android.sdk.api.session.events.model.isVideoMessage import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent @@ -29,6 +28,7 @@ import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper import org.matrix.android.sdk.internal.database.model.TimelineEventEntity import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields import org.matrix.android.sdk.internal.database.query.where +import org.matrix.android.sdk.internal.database.query.whereRoomId import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.task.TaskExecutor import javax.inject.Inject @@ -53,8 +53,7 @@ internal class TimelineEventDataSource @Inject constructor(private val realmSess fun getAttachmentMessages(roomId: String): List<TimelineEvent> { // TODO pretty bad query.. maybe we should denormalize clear type in base? return realmSessionProvider.withRealm { realm -> - realm.where<TimelineEventEntity>() - .equalTo(TimelineEventEntityFields.ROOM_ID, roomId) + TimelineEventEntity.whereRoomId(realm, roomId) .sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.ASCENDING) .findAll() ?.mapNotNull { timelineEventMapper.map(it).takeIf { it.root.isImageMessage() || it.root.isVideoMessage() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt index 5c30dc20d9df8e44ef8dc366feb0633ea2fd7b0c..de79661de05d5d7bb734d856ab092b706a7f71a9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt @@ -99,9 +99,7 @@ internal class TimelineEventDecryptor @Inject constructor( executor?.execute { Realm.getInstance(realmConfiguration).use { realm -> try { - runBlocking { - processDecryptRequest(request, realm) - } + processDecryptRequest(request, realm) } catch (e: InterruptedException) { Timber.i("Decryption got interrupted") } @@ -121,7 +119,7 @@ internal class TimelineEventDecryptor @Inject constructor( } } - private suspend fun processDecryptRequest(request: DecryptionRequest, realm: Realm) { + private fun processDecryptRequest(request: DecryptionRequest, realm: Realm) { val event = request.event val timelineId = request.timelineId @@ -132,7 +130,8 @@ internal class TimelineEventDecryptor @Inject constructor( return } try { - val result = cryptoService.decryptEvent(request.event, timelineId) + // note: runBlocking should be used here while we are in realm single thread executor, to avoid thread switching + val result = runBlocking { cryptoService.decryptEvent(request.event, timelineId) } Timber.v("Successfully decrypted event ${event.eventId}") realm.executeTransaction { val eventId = event.eventId ?: return@executeTransaction diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt index d3f24a8568a4a8ba5107f20668890b826019932f..e5dd8aab304bd88ce008425b706e5eb9a494f666 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt @@ -44,6 +44,7 @@ import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.StreamEventsManager import org.matrix.android.sdk.internal.util.awaitTransaction +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject @@ -54,7 +55,9 @@ internal class TokenChunkEventPersistor @Inject constructor( @SessionDatabase private val monarchy: Monarchy, @UserId private val userId: String, private val lightweightSettingsStorage: LightweightSettingsStorage, - private val liveEventManager: Lazy<StreamEventsManager>) { + private val liveEventManager: Lazy<StreamEventsManager>, + private val clock: Clock, +) { enum class Result { SHOULD_FETCH_MORE, @@ -166,7 +169,7 @@ internal class TokenChunkEventPersistor @Inject constructor( val eventList = receivedChunk.events val stateEvents = receivedChunk.stateEvents - val now = System.currentTimeMillis() + val now = clock.epochMillis() stateEvents?.forEach { stateEvent -> val ageLocalTs = stateEvent.unsignedData?.age?.let { now - it } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/UIEchoManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/UIEchoManager.kt index bb926232493733b2f3d5e4203b2d524f2b017c14..828e01955a0ab6cedc2d744f1ac249bf1f30b7ae 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/UIEchoManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/UIEchoManager.kt @@ -24,10 +24,14 @@ import org.matrix.android.sdk.api.session.room.model.ReactionAggregatedSummary import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import java.util.Collections -internal class UIEchoManager(private val listener: Listener) { +internal class UIEchoManager( + private val listener: Listener, + private val clock: Clock, +) { interface Listener { fun rebuildEvent(eventId: String, builder: (TimelineEvent) -> TimelineEvent?): Boolean @@ -98,9 +102,7 @@ internal class UIEchoManager(private val listener: Listener) { val relatedEventID = timelineEvent.eventId val contents = inMemoryReactions[relatedEventID] ?: return timelineEvent - var existingAnnotationSummary = timelineEvent.annotations ?: EventAnnotationsSummary( - relatedEventID - ) + var existingAnnotationSummary = timelineEvent.annotations ?: EventAnnotationsSummary() val updateReactions = existingAnnotationSummary.reactionsSummary.toMutableList() contents.forEach { uiEchoReaction -> @@ -111,7 +113,7 @@ internal class UIEchoManager(private val listener: Listener) { key = uiEchoReaction.reaction, count = 1, addedByMe = true, - firstTimestamp = System.currentTimeMillis(), + firstTimestamp = clock.epochMillis(), sourceEvents = emptyList(), localEchoEvents = listOf(uiEchoReaction.localEchoId) ).let { updateReactions.add(it) } @@ -145,7 +147,7 @@ internal class UIEchoManager(private val listener: Listener) { fun updateSentStateWithUiEcho(timelineEvent: TimelineEvent): TimelineEvent { if (timelineEvent.root.sendState.isSent()) return timelineEvent val inMemoryState = inMemorySendingStates[timelineEvent.eventId] ?: return timelineEvent - // Timber.v("## ${System.currentTimeMillis()} Send event refresh echo with live state $inMemoryState from state ${element.root.sendState}") + // Timber.v("## ${clock.epochMillis()} Send event refresh echo with live state $inMemoryState from state ${element.root.sendState}") return timelineEvent.copy( root = timelineEvent.root.copyAll() .also { it.sendState = inMemoryState } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt index 3ba7d11c3df2b7d7d9eeb235f06385680a8c1297..fcaf3b60a761a1f156d91fb5c4d2dc06eeaa3432 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/search/SearchTask.kt @@ -87,7 +87,7 @@ internal class DefaultSearchTask @Inject constructor( results = searchCategories.roomEvents?.results?.map { searchResponseItem -> val localThreadEventDetails = localTimelineEvents - ?.firstOrNull { it.eventId == searchResponseItem.event.eventId } + ?.firstOrNull { it.eventId == searchResponseItem.event.eventId } ?.root ?.asDomain() ?.threadDetails diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpace.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpace.kt index 303eda49d89d216e94a4faab02fd5add6e53ee00..178a29a5a01c06ea7d31de8142ad173c18b53be4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpace.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpace.kt @@ -60,7 +60,7 @@ internal class DefaultSpace( } ?: viaParameterFinder.computeViaParams(roomId, 3)) - room.sendStateEvent( + room.stateService().sendStateEvent( eventType = EventType.STATE_SPACE_CHILD, stateKey = roomId, body = SpaceChildContent( @@ -79,7 +79,7 @@ internal class DefaultSpace( // return // edit state event and set via to null - room.sendStateEvent( + room.stateService().sendStateEvent( eventType = EventType.STATE_SPACE_CHILD, stateKey = roomId, body = SpaceChildContent( @@ -91,19 +91,19 @@ internal class DefaultSpace( } override fun getChildInfo(roomId: String): SpaceChildContent? { - return room.getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId)) + return room.stateService().getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId)) .firstOrNull() ?.content.toModel<SpaceChildContent>() } override suspend fun setChildrenOrder(roomId: String, order: String?) { - val existing = room.getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId)) + val existing = room.stateService().getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId)) .firstOrNull() ?.content.toModel<SpaceChildContent>() ?: throw IllegalArgumentException("$roomId is not a child of this space") // edit state event and set via to null - room.sendStateEvent( + room.stateService().sendStateEvent( eventType = EventType.STATE_SPACE_CHILD, stateKey = roomId, body = SpaceChildContent( @@ -140,7 +140,7 @@ internal class DefaultSpace( // } override suspend fun setChildrenSuggested(roomId: String, suggested: Boolean) { - val existing = room.getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId)) + val existing = room.stateService().getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId)) .firstOrNull() ?.content.toModel<SpaceChildContent>() ?: throw IllegalArgumentException("$roomId is not a child of this space") @@ -150,7 +150,7 @@ internal class DefaultSpace( return } // edit state event and set via to null - room.sendStateEvent( + room.stateService().sendStateEvent( eventType = EventType.STATE_SPACE_CHILD, stateKey = roomId, body = SpaceChildContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt index 355039b22c704d8dce8038764f60b7e362a3cd0b..9320665688af7281e01c0182aa683be5e3516b35 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt @@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.RoomSortOrder +import org.matrix.android.sdk.api.session.room.getStateEvent import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent @@ -258,7 +259,7 @@ internal class DefaultSpaceService @Inject constructor( val room = roomGetter.getRoom(childRoomId) ?: throw IllegalArgumentException("Unknown Room $childRoomId") - room.sendStateEvent( + room.stateService().sendStateEvent( eventType = EventType.STATE_SPACE_PARENT, stateKey = parentSpaceId, body = SpaceParentContent( @@ -276,7 +277,7 @@ internal class DefaultSpaceService @Inject constructor( if (existingEvent != null) { // Should i check if it was sent by me? // we don't check power level, it will throw if you cannot do that - room.sendStateEvent( + room.stateService().sendStateEvent( eventType = EventType.STATE_SPACE_PARENT, stateKey = parentSpaceId, body = SpaceParentContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStatusRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStatusRepository.kt index bd20ada28b03e9d6eeaf7f484b518732d08d8ed3..8e0c3422b933d81806fdfa9126a07f30b19fa6fa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStatusRepository.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStatusRepository.kt @@ -20,6 +20,7 @@ import com.squareup.moshi.JsonClass import okio.buffer import okio.source import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import java.io.File @@ -46,7 +47,10 @@ internal interface InitialSyncStatusRepository { /** * This class handle the current status of an initial sync and persist it on the disk, to be robust against crash */ -internal class FileInitialSyncStatusRepository(directory: File) : InitialSyncStatusRepository { +internal class FileInitialSyncStatusRepository( + directory: File, + private val clock: Clock, +) : InitialSyncStatusRepository { companion object { // After 2 hours, we consider that the downloaded file is outdated: @@ -64,7 +68,7 @@ internal class FileInitialSyncStatusRepository(directory: File) : InitialSyncSta ensureCache() val state = cache?.step ?: InitialSyncStatus.STEP_INIT return if (state >= InitialSyncStatus.STEP_DOWNLOADED && - System.currentTimeMillis() > (cache?.downloadedDate ?: 0) + INIT_SYNC_FILE_LIFETIME) { + clock.epochMillis() > (cache?.downloadedDate ?: 0) + INIT_SYNC_FILE_LIFETIME) { Timber.d("INIT_SYNC downloaded file is outdated, download it again") // The downloaded file is outdated setStep(InitialSyncStatus.STEP_INIT) @@ -79,7 +83,7 @@ internal class FileInitialSyncStatusRepository(directory: File) : InitialSyncSta if (step == InitialSyncStatus.STEP_DOWNLOADED) { // Also store the downloaded date newStatus = newStatus.copy( - downloadedDate = System.currentTimeMillis() + downloadedDate = clock.epochMillis() ) } cache = newStatus diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt index 4f1fe43b7ddcc24dee4b7b7548055c8193f8ac04..42cd972e0cf93bda572d5ed58d801feba5bfcc20 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt @@ -34,11 +34,12 @@ internal enum class SyncPresence(val value: String) { companion object { fun from(presenceEnum: PresenceEnum): SyncPresence { return when (presenceEnum) { - PresenceEnum.ONLINE -> Online - PresenceEnum.OFFLINE -> Offline + PresenceEnum.ONLINE -> Online + PresenceEnum.OFFLINE -> Offline PresenceEnum.UNAVAILABLE -> Unavailable } } + fun from(s: String?): SyncPresence? = values().find { it.value == s } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt index 97850e81d32084ea8a5fac97043359aa46cc4694..02a7a9a37fe13aef18d645a7e732b530c0cbb5a2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.sync import androidx.work.ExistingPeriodicWorkPolicy import com.zhuinden.monarchy.Monarchy -import org.matrix.android.sdk.api.pushrules.PushRuleService -import org.matrix.android.sdk.api.pushrules.RuleScope import org.matrix.android.sdk.api.session.initsync.InitSyncStep +import org.matrix.android.sdk.api.session.pushrules.PushRuleService +import org.matrix.android.sdk.api.session.pushrules.RuleScope import org.matrix.android.sdk.api.session.sync.model.GroupsSyncResponse import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse import org.matrix.android.sdk.api.session.sync.model.SyncResponse @@ -34,7 +34,7 @@ import org.matrix.android.sdk.internal.session.dispatchTo import org.matrix.android.sdk.internal.session.group.GetGroupDataWorker import org.matrix.android.sdk.internal.session.initsync.ProgressReporter import org.matrix.android.sdk.internal.session.initsync.reportSubtask -import org.matrix.android.sdk.internal.session.notification.ProcessEventForPushTask +import org.matrix.android.sdk.internal.session.pushrules.ProcessEventForPushTask import org.matrix.android.sdk.internal.session.sync.handler.CryptoSyncHandler import org.matrix.android.sdk.internal.session.sync.handler.GroupSyncHandler import org.matrix.android.sdk.internal.session.sync.handler.PresenceSyncHandler diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt index b56f89774983a8e453e79b4cc16aed6c6974080a..f88d9731015b2fc504ceda7e0b0782a82532a264 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt @@ -44,6 +44,7 @@ import org.matrix.android.sdk.internal.session.sync.parsing.InitialSyncResponseP import org.matrix.android.sdk.internal.session.user.UserStore import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.logDuration +import org.matrix.android.sdk.internal.util.time.Clock import retrofit2.Response import retrofit2.awaitResponse import timber.log.Timber @@ -78,11 +79,12 @@ internal class DefaultSyncTask @Inject constructor( @SessionFilesDirectory private val fileDirectory: File, private val syncResponseParser: InitialSyncResponseParser, - private val roomSyncEphemeralTemporaryStore: RoomSyncEphemeralTemporaryStore + private val roomSyncEphemeralTemporaryStore: RoomSyncEphemeralTemporaryStore, + private val clock: Clock, ) : SyncTask { private val workingDir = File(fileDirectory, "is") - private val initialSyncStatusRepository: InitialSyncStatusRepository = FileInitialSyncStatusRepository(workingDir) + private val initialSyncStatusRepository: InitialSyncStatusRepository = FileInitialSyncStatusRepository(workingDir, clock) override suspend fun execute(params: SyncTask.Params): SyncResponse { return syncTaskSequencer.post { @@ -107,11 +109,12 @@ internal class DefaultSyncTask @Inject constructor( val isInitialSync = token == null if (isInitialSync) { // We might want to get the user information in parallel too - val user = tryOrNull { session.getProfileAsUser(userId) } + val user = tryOrNull { session.profileService().getProfileAsUser(userId) } userStore.createOrUpdate( userId = userId, displayName = user?.displayName, - avatarUrl = user?.avatarUrl) + avatarUrl = user?.avatarUrl + ) defaultSyncStatusService.startRoot(InitSyncStep.ImportingAccount, 100) } // Maybe refresh the homeserver capabilities data we know @@ -124,7 +127,7 @@ internal class DefaultSyncTask @Inject constructor( if (isInitialSync) { Timber.tag(loggerTag.value).d("INIT_SYNC with filter: ${requestParams["filter"]}") val initSyncStrategy = initialSyncStrategy - logDuration("INIT_SYNC strategy: $initSyncStrategy", loggerTag) { + logDuration("INIT_SYNC strategy: $initSyncStrategy", loggerTag, clock) { if (initSyncStrategy is InitialSyncStrategy.Optimized) { roomSyncEphemeralTemporaryStore.reset() workingDir.mkdirs() @@ -135,7 +138,7 @@ internal class DefaultSyncTask @Inject constructor( // Delete all files workingDir.deleteRecursively() } else { - val syncResponse = logDuration("INIT_SYNC Request", loggerTag) { + val syncResponse = logDuration("INIT_SYNC Request", loggerTag, clock) { executeRequest(globalErrorReceiver) { syncAPI.sync( params = requestParams, @@ -146,7 +149,7 @@ internal class DefaultSyncTask @Inject constructor( // We cannot distinguish request and download in this case. syncStatisticsData.requestInitSyncTime = SystemClock.elapsedRealtime() syncStatisticsData.downloadInitSyncTime = syncStatisticsData.requestInitSyncTime - logDuration("INIT_SYNC Database insertion", loggerTag) { + logDuration("INIT_SYNC Database insertion", loggerTag, clock) { syncResponseHandler.handleResponse(syncResponse, token, defaultSyncStatusService) } syncResponseToReturn = syncResponse @@ -172,12 +175,14 @@ internal class DefaultSyncTask @Inject constructor( val nbToDevice = syncResponse.toDevice?.events.orEmpty().size val nextBatch = syncResponse.nextBatch Timber.tag(loggerTag.value).d( - "Incremental sync request parsing, $nbRooms room(s) $nbToDevice toDevice(s). Got nextBatch: $nextBatch" + "Incremental sync request parsing, $nbRooms room(s) $nbToDevice toDevice(s). Got nextBatch: $nextBatch" + ) + defaultSyncStatusService.setStatus( + SyncStatusService.Status.IncrementalSyncParsing( + rooms = nbRooms, + toDevice = nbToDevice + ) ) - defaultSyncStatusService.setStatus(SyncStatusService.Status.IncrementalSyncParsing( - rooms = nbRooms, - toDevice = nbToDevice - )) syncResponseHandler.handleResponse(syncResponse, token, null) syncResponseToReturn = syncResponse Timber.tag(loggerTag.value).d("Incremental sync done") @@ -201,14 +206,14 @@ internal class DefaultSyncTask @Inject constructor( } } else { initialSyncStatusRepository.setStep(InitialSyncStatus.STEP_DOWNLOADING) - val syncResponse = logDuration("INIT_SYNC Perform server request", loggerTag) { + val syncResponse = logDuration("INIT_SYNC Perform server request", loggerTag, clock) { reportSubtask(defaultSyncStatusService, InitSyncStep.ServerComputing, 1, 0.2f) { getSyncResponse(requestParams, MAX_NUMBER_OF_RETRY_AFTER_TIMEOUT) } } syncStatisticsData.requestInitSyncTime = SystemClock.elapsedRealtime() if (syncResponse.isSuccessful) { - logDuration("INIT_SYNC Download and save to file", loggerTag) { + logDuration("INIT_SYNC Download and save to file", loggerTag, clock) { reportSubtask(defaultSyncStatusService, InitSyncStep.Downloading, 1, 0.1f) { syncResponse.body()?.byteStream()?.use { inputStream -> workingFile.outputStream().use { outputStream -> @@ -247,8 +252,8 @@ internal class DefaultSyncTask @Inject constructor( } private suspend fun handleSyncFile(workingFile: File, initSyncStrategy: InitialSyncStrategy.Optimized): SyncResponse { - return logDuration("INIT_SYNC handleSyncFile()", loggerTag) { - val syncResponse = logDuration("INIT_SYNC Read file and parse", loggerTag) { + return logDuration("INIT_SYNC handleSyncFile()", loggerTag, clock) { + val syncResponse = logDuration("INIT_SYNC Read file and parse", loggerTag, clock) { syncResponseParser.parse(initSyncStrategy, workingFile) } initialSyncStatusRepository.setStep(InitialSyncStatus.STEP_PARSED) @@ -257,7 +262,7 @@ internal class DefaultSyncTask @Inject constructor( val nbOfJoinedRoomsInFile = syncResponse.rooms?.join?.values?.count { it.ephemeral is LazyRoomSyncEphemeral.Stored } Timber.tag(loggerTag.value).d("INIT_SYNC $nbOfJoinedRooms rooms, $nbOfJoinedRoomsInFile ephemeral stored into files") - logDuration("INIT_SYNC Database insertion", loggerTag) { + logDuration("INIT_SYNC Database insertion", loggerTag, clock) { syncResponseHandler.handleResponse(syncResponse, null, defaultSyncStatusService) } initialSyncStatusRepository.setStep(InitialSyncStatus.STEP_SUCCESS) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt index 7f80486c70dee176651556b260236d72a1ba8516..c213ea4bcfdbac5a68f5b19ab46e4b98cc4513c9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt @@ -20,17 +20,19 @@ import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmList import io.realm.kotlin.where -import org.matrix.android.sdk.api.pushrules.RuleScope -import org.matrix.android.sdk.api.pushrules.RuleSetKey -import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse +import org.matrix.android.sdk.api.failure.GlobalError +import org.matrix.android.sdk.api.failure.InitialSyncRequestReason import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.pushrules.RuleScope +import org.matrix.android.sdk.api.session.pushrules.RuleSetKey import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.sync.model.InvitedRoomSync import org.matrix.android.sdk.api.session.sync.model.UserAccountDataSync +import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.database.mapper.ContentMapper import org.matrix.android.sdk.internal.database.mapper.PushRulesMapper import org.matrix.android.sdk.internal.database.mapper.asDomain @@ -39,14 +41,20 @@ import org.matrix.android.sdk.internal.database.model.IgnoredUserEntity import org.matrix.android.sdk.internal.database.model.PushRulesEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields +import org.matrix.android.sdk.internal.database.model.TimelineEventEntity import org.matrix.android.sdk.internal.database.model.UserAccountDataEntity import org.matrix.android.sdk.internal.database.model.UserAccountDataEntityFields import org.matrix.android.sdk.internal.database.model.deleteOnCascade +import org.matrix.android.sdk.internal.database.query.findAllFrom import org.matrix.android.sdk.internal.database.query.getDirectRooms import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.session.SessionListeners +import org.matrix.android.sdk.internal.session.dispatchTo +import org.matrix.android.sdk.internal.session.pushers.GetPushRulesResponse import org.matrix.android.sdk.internal.session.room.RoomAvatarResolver import org.matrix.android.sdk.internal.session.room.membership.RoomDisplayNameResolver import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper @@ -65,7 +73,10 @@ internal class UserAccountDataSyncHandler @Inject constructor( private val directChatsHelper: DirectChatsHelper, private val updateUserAccountDataTask: UpdateUserAccountDataTask, private val roomAvatarResolver: RoomAvatarResolver, - private val roomDisplayNameResolver: RoomDisplayNameResolver + private val roomDisplayNameResolver: RoomDisplayNameResolver, + @SessionId private val sessionId: String, + private val sessionManager: SessionManager, + private val sessionListeners: SessionListeners ) { fun handle(realm: Realm, accountData: UserAccountDataSync?) { @@ -184,12 +195,36 @@ internal class UserAccountDataSyncHandler @Inject constructor( private fun handleIgnoredUsers(realm: Realm, event: UserAccountDataEvent) { val userIds = event.content.toModel<IgnoredUsersContent>()?.ignoredUsers?.keys ?: return - realm.where(IgnoredUserEntity::class.java) - .findAll() - .deleteAllFromRealm() + val currentIgnoredUsers = realm.where(IgnoredUserEntity::class.java).findAll() + val currentIgnoredUserIds = currentIgnoredUsers.map { it.userId } + // Delete the previous list + currentIgnoredUsers.deleteAllFromRealm() // And save the new received list userIds.forEach { realm.createObject(IgnoredUserEntity::class.java).apply { userId = it } } - // TODO If not initial sync, we should execute a init sync + + // Delete all the TimelineEvents for all the ignored users + // See https://spec.matrix.org/latest/client-server-api/#client-behaviour-22 : + // "Once ignored, the client will no longer receive events sent by that user, with the exception of state events" + // So just delete all non-state events from our local storage. + TimelineEventEntity.findAllFrom(realm, userIds) + .also { Timber.d("Deleting ${it.size} TimelineEventEntity from ignored users") } + .forEach { + it.deleteOnCascade(true) + } + + // Handle the case when some users are unignored from another session + val mustRefreshCache = currentIgnoredUserIds.any { currentIgnoredUserId -> currentIgnoredUserId !in userIds } + if (mustRefreshCache) { + Timber.d("A user has been unignored from another session, an initial sync should be performed") + dispatchMustRefresh() + } + } + + private fun dispatchMustRefresh() { + val session = sessionManager.getSessionComponent(sessionId)?.session() + session.dispatchTo(sessionListeners) { safeSession, listener -> + listener.onGlobalError(safeSession, GlobalError.InitialSyncRequest(InitialSyncRequestReason.IGNORED_USERS_LIST_CHANGE)) + } } private fun handleBreadcrumbs(realm: Realm, event: UserAccountDataEvent) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt index 2c84f1e692f523406a8ca3abd41c25ab52ad00f6..77bee18df932814a3bab3fbbcdf2f11712cf90dc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt @@ -44,12 +44,14 @@ internal class ReadReceiptHandler @Inject constructor( companion object { - fun createContent(userId: String, eventId: String): ReadReceiptContent { + fun createContent(userId: String, + eventId: String, + currentTimeMillis: Long): ReadReceiptContent { return mapOf( eventId to mapOf( READ_KEY to mapOf( userId to mapOf( - TIMESTAMP_KEY to System.currentTimeMillis().toDouble() + TIMESTAMP_KEY to currentTimeMillis.toDouble() ) ) ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt index afd8e1bb99a5b163d410181ae32e335bddd79678..5437a015fdf25d17dfb7bec7796c7c1cbc423d7b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt @@ -79,22 +79,26 @@ import org.matrix.android.sdk.internal.session.room.typing.TypingEventContent import org.matrix.android.sdk.internal.session.sync.SyncResponsePostTreatmentAggregator import org.matrix.android.sdk.internal.session.sync.parsing.RoomSyncAccountDataHandler import org.matrix.android.sdk.internal.util.computeBestChunkSize +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber import javax.inject.Inject -internal class RoomSyncHandler @Inject constructor(private val readReceiptHandler: ReadReceiptHandler, - private val roomSummaryUpdater: RoomSummaryUpdater, - private val roomAccountDataHandler: RoomSyncAccountDataHandler, - private val cryptoService: DefaultCryptoService, - private val roomMemberEventHandler: RoomMemberEventHandler, - private val roomTypingUsersHandler: RoomTypingUsersHandler, - private val threadsAwarenessHandler: ThreadsAwarenessHandler, - private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource, - @UserId private val userId: String, - private val homeServerCapabilitiesService: HomeServerCapabilitiesService, - private val lightweightSettingsStorage: LightweightSettingsStorage, - private val timelineInput: TimelineInput, - private val liveEventService: Lazy<StreamEventsManager>) { +internal class RoomSyncHandler @Inject constructor( + private val readReceiptHandler: ReadReceiptHandler, + private val roomSummaryUpdater: RoomSummaryUpdater, + private val roomAccountDataHandler: RoomSyncAccountDataHandler, + private val cryptoService: DefaultCryptoService, + private val roomMemberEventHandler: RoomMemberEventHandler, + private val roomTypingUsersHandler: RoomTypingUsersHandler, + private val threadsAwarenessHandler: ThreadsAwarenessHandler, + private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource, + @UserId private val userId: String, + private val homeServerCapabilitiesService: HomeServerCapabilitiesService, + private val lightweightSettingsStorage: LightweightSettingsStorage, + private val timelineInput: TimelineInput, + private val liveEventService: Lazy<StreamEventsManager>, + private val clock: Clock, +) { sealed class HandlingStrategy { data class JOINED(val data: Map<String, RoomSync>) : HandlingStrategy() @@ -102,11 +106,11 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle data class LEFT(val data: Map<String, RoomSync>) : HandlingStrategy() } - suspend fun handle(realm: Realm, - roomsSyncResponse: RoomsSyncResponse, - isInitialSync: Boolean, - aggregator: SyncResponsePostTreatmentAggregator, - reporter: ProgressReporter? = null) { + fun handle(realm: Realm, + roomsSyncResponse: RoomsSyncResponse, + isInitialSync: Boolean, + aggregator: SyncResponsePostTreatmentAggregator, + reporter: ProgressReporter? = null) { handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), isInitialSync, aggregator, reporter) handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), isInitialSync, aggregator, reporter) handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), isInitialSync, aggregator, reporter) @@ -120,17 +124,17 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle } // PRIVATE METHODS ***************************************************************************** - private suspend fun handleRoomSync(realm: Realm, - handlingStrategy: HandlingStrategy, - isInitialSync: Boolean, - aggregator: SyncResponsePostTreatmentAggregator, - reporter: ProgressReporter?) { + private fun handleRoomSync(realm: Realm, + handlingStrategy: HandlingStrategy, + isInitialSync: Boolean, + aggregator: SyncResponsePostTreatmentAggregator, + reporter: ProgressReporter?) { val insertType = if (isInitialSync) { EventInsertType.INITIAL_SYNC } else { EventInsertType.INCREMENTAL_SYNC } - val syncLocalTimeStampMillis = System.currentTimeMillis() + val syncLocalTimeStampMillis = clock.epochMillis() val rooms = when (handlingStrategy) { is HandlingStrategy.JOINED -> { if (isInitialSync && initialSyncStrategy is InitialSyncStrategy.Optimized) { @@ -157,11 +161,11 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle realm.insertOrUpdate(rooms) } - private suspend fun insertJoinRoomsFromInitSync(realm: Realm, - handlingStrategy: HandlingStrategy.JOINED, - syncLocalTimeStampMillis: Long, - aggregator: SyncResponsePostTreatmentAggregator, - reporter: ProgressReporter?) { + private fun insertJoinRoomsFromInitSync(realm: Realm, + handlingStrategy: HandlingStrategy.JOINED, + syncLocalTimeStampMillis: Long, + aggregator: SyncResponsePostTreatmentAggregator, + reporter: ProgressReporter?) { val bestChunkSize = computeBestChunkSize( listSize = handlingStrategy.data.keys.size, limit = (initialSyncStrategy as? InitialSyncStrategy.Optimized)?.maxRoomsToInsert ?: Int.MAX_VALUE @@ -199,12 +203,12 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle } } - private suspend fun handleJoinedRoom(realm: Realm, - roomId: String, - roomSync: RoomSync, - insertType: EventInsertType, - syncLocalTimestampMillis: Long, - aggregator: SyncResponsePostTreatmentAggregator): RoomEntity { + private fun handleJoinedRoom(realm: Realm, + roomId: String, + roomSync: RoomSync, + insertType: EventInsertType, + syncLocalTimestampMillis: Long, + aggregator: SyncResponsePostTreatmentAggregator): RoomEntity { Timber.v("Handle join sync for room $roomId") val isInitialSync = insertType == EventInsertType.INITIAL_SYNC @@ -353,15 +357,15 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle return roomEntity } - private suspend fun handleTimelineEvents(realm: Realm, - roomId: String, - roomEntity: RoomEntity, - eventList: List<Event>, - prevToken: String? = null, - isLimited: Boolean = true, - insertType: EventInsertType, - syncLocalTimestampMillis: Long, - aggregator: SyncResponsePostTreatmentAggregator): ChunkEntity { + private fun handleTimelineEvents(realm: Realm, + roomId: String, + roomEntity: RoomEntity, + eventList: List<Event>, + prevToken: String? = null, + isLimited: Boolean = true, + insertType: EventInsertType, + syncLocalTimestampMillis: Long, + aggregator: SyncResponsePostTreatmentAggregator): ChunkEntity { val lastChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomEntity.roomId) if (isLimited && lastChunk != null) { lastChunk.deleteOnCascade(deleteStateEvents = false, canDeleteRoot = true) @@ -389,8 +393,10 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle liveEventService.get().dispatchLiveEventReceived(event, roomId, isInitialSync) if (event.isEncrypted() && !isInitialSync) { - runBlocking { + try { decryptIfNeeded(event, roomId) + } catch (e: InterruptedException) { + Timber.i("Decryption got interrupted") } } var contentToInject: String? = null @@ -421,7 +427,8 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle roomId = roomId, eventEntity = eventEntity, direction = PaginationDirection.FORWARDS, - roomMemberContentsByUser = roomMemberContentsByUser) + roomMemberContentsByUser = roomMemberContentsByUser + ) if (lightweightSettingsStorage.areThreadMessagesEnabled()) { eventEntity.rootThreadEventId?.let { // This is a thread event @@ -437,7 +444,9 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle threadEventEntity = eventEntity, roomMemberContentsByUser = roomMemberContentsByUser, userId = userId, - roomEntity = roomEntity) + roomEntity = roomEntity, + currentTimeMillis = clock.epochMillis(), + ) } } ?: run { // This is a normal event or a root thread one @@ -475,7 +484,8 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle roomId = roomId, realm = realm, chunkEntity = chunkEntity, - currentUserId = userId) + currentUserId = userId + ) } // posting new events to timeline if any is registered @@ -505,10 +515,11 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle } } - private suspend fun decryptIfNeeded(event: Event, roomId: String) { + private fun decryptIfNeeded(event: Event, roomId: String) { try { // Event from sync does not have roomId, so add it to the event first - val result = cryptoService.decryptEvent(event.copy(roomId = roomId), "") + // note: runBlocking should be used here while we are in realm single thread executor, to avoid thread switching + val result = runBlocking { cryptoService.decryptEvent(event.copy(roomId = roomId), "") } event.mxDecryptionResult = OlmDecryptionResult( payload = result.clearEvent, senderKey = result.senderCurve25519Key, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt index c67c0e350e09ee2e8bc975b517f6ee2c4df9b82c..f183c4cb28cd5c67f139270255114c817925e6f3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt @@ -42,7 +42,7 @@ private const val DEFAULT_DELAY_MILLIS = 30_000L * Possible next worker : None */ internal class SyncWorker(context: Context, workerParameters: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<SyncWorker.Params>(context, workerParameters, sessionManager, Params::class.java) { + SessionSafeCoroutineWorker<SyncWorker.Params>(context, workerParameters, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/thirdparty/DefaultThirdPartyService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/thirdparty/DefaultThirdPartyService.kt index fdd5524fc22219696c581efcfb664b7233582413..210cb192e7f7c3c832432041d87982c025548a93 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/thirdparty/DefaultThirdPartyService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/thirdparty/DefaultThirdPartyService.kt @@ -23,7 +23,7 @@ import javax.inject.Inject internal class DefaultThirdPartyService @Inject constructor(private val getThirdPartyProtocolTask: GetThirdPartyProtocolsTask, private val getThirdPartyUserTask: GetThirdPartyUserTask) : - ThirdPartyService { + ThirdPartyService { override suspend fun getThirdPartyProtocols(): Map<String, ThirdPartyProtocol> { return getThirdPartyProtocolTask.execute(Unit) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserModule.kt index 4dfc7586aecc7bf5af7485579d16fc0f181e866f..c205c4f1c6d31b512e304b56e5c00346e6a2f216 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserModule.kt @@ -21,9 +21,7 @@ import dagger.Module import dagger.Provides import org.matrix.android.sdk.api.session.user.UserService import org.matrix.android.sdk.internal.session.SessionScope -import org.matrix.android.sdk.internal.session.user.accountdata.DefaultSaveIgnoredUsersTask import org.matrix.android.sdk.internal.session.user.accountdata.DefaultUpdateIgnoredUserIdsTask -import org.matrix.android.sdk.internal.session.user.accountdata.SaveIgnoredUsersTask import org.matrix.android.sdk.internal.session.user.accountdata.UpdateIgnoredUserIdsTask import org.matrix.android.sdk.internal.session.user.model.DefaultSearchUserTask import org.matrix.android.sdk.internal.session.user.model.SearchUserTask @@ -48,9 +46,6 @@ internal abstract class UserModule { @Binds abstract fun bindSearchUserTask(task: DefaultSearchUserTask): SearchUserTask - @Binds - abstract fun bindSaveIgnoredUsersTask(task: DefaultSaveIgnoredUsersTask): SaveIgnoredUsersTask - @Binds abstract fun bindUpdateIgnoredUserIdsTask(task: DefaultUpdateIgnoredUserIdsTask): UpdateIgnoredUserIdsTask diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveIgnoredUsersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveIgnoredUsersTask.kt deleted file mode 100644 index 63c0ce645eb9d792e5e8ab1c1047cdf9ac87eb4b..0000000000000000000000000000000000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveIgnoredUsersTask.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.internal.session.user.accountdata - -import com.zhuinden.monarchy.Monarchy -import org.matrix.android.sdk.internal.database.model.IgnoredUserEntity -import org.matrix.android.sdk.internal.di.SessionDatabase -import org.matrix.android.sdk.internal.task.Task -import org.matrix.android.sdk.internal.util.awaitTransaction -import javax.inject.Inject - -/** - * Save the ignored users list in DB - */ -internal interface SaveIgnoredUsersTask : Task<SaveIgnoredUsersTask.Params, Unit> { - data class Params( - val userIds: List<String> - ) -} - -internal class DefaultSaveIgnoredUsersTask @Inject constructor(@SessionDatabase private val monarchy: Monarchy) : SaveIgnoredUsersTask { - - override suspend fun execute(params: SaveIgnoredUsersTask.Params) { - monarchy.awaitTransaction { realm -> - // clear current ignored users - realm.where(IgnoredUserEntity::class.java) - .findAll() - .deleteAllFromRealm() - - // And save the new received list - params.userIds.forEach { realm.createObject(IgnoredUserEntity::class.java).apply { userId = it } } - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt index 445b78104cfb7bd0431ab34a4296f9266a07bd13..173161f8aeb08fdc4bca5e5a8db938cd0e6e18da 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt @@ -38,7 +38,6 @@ internal interface UpdateIgnoredUserIdsTask : Task<UpdateIgnoredUserIdsTask.Para internal class DefaultUpdateIgnoredUserIdsTask @Inject constructor( private val accountDataApi: AccountDataAPI, @SessionDatabase private val monarchy: Monarchy, - private val saveIgnoredUsersTask: SaveIgnoredUsersTask, @UserId private val userId: String, private val globalErrorReceiver: GlobalErrorReceiver ) : UpdateIgnoredUserIdsTask { @@ -66,8 +65,5 @@ internal class DefaultUpdateIgnoredUserIdsTask @Inject constructor( executeRequest(globalErrorReceiver) { accountDataApi.setAccountData(userId, UserAccountDataTypes.TYPE_IGNORED_USER_LIST, body) } - - // Update the DB right now (do not wait for the sync to come back with updated data, for a faster UI update) - saveIgnoredUsersTask.execute(SaveIgnoredUsersTask.Params(list)) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/CreateWidgetTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/CreateWidgetTask.kt index 18a043be453177a78d791e88ee854ad6a6eb1a0c..06508def1c4e2787e75874803d70d8da26951e65 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/CreateWidgetTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/CreateWidgetTask.kt @@ -29,9 +29,10 @@ import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.task.Task +import timber.log.Timber import javax.inject.Inject -internal interface CreateWidgetTask : Task<CreateWidgetTask.Params, Unit> { +internal interface CreateWidgetTask : Task<CreateWidgetTask.Params, String> { data class Params( val roomId: String, @@ -45,8 +46,8 @@ internal class DefaultCreateWidgetTask @Inject constructor(@SessionDatabase priv @UserId private val userId: String, private val globalErrorReceiver: GlobalErrorReceiver) : CreateWidgetTask { - override suspend fun execute(params: CreateWidgetTask.Params) { - executeRequest(globalErrorReceiver) { + override suspend fun execute(params: CreateWidgetTask.Params): String { + val response = executeRequest(globalErrorReceiver) { roomAPI.sendStateEvent( roomId = params.roomId, stateEventType = EventType.STATE_ROOM_WIDGET_LEGACY, @@ -60,5 +61,8 @@ internal class DefaultCreateWidgetTask @Inject constructor(@SessionDatabase priv .and() .equalTo(CurrentStateEventEntityFields.ROOT.SENDER, userId) } + return response.eventId.also { + Timber.d("Widget state event: $it just sent in room ${params.roomId}") + } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt index 10b4f7f7d7d0c73e3d4d30f40b14d1793a22149f..9f42688f7d63ebf732f6328387711dba6c9af310 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt @@ -29,7 +29,7 @@ import javax.inject.Inject internal class DefaultWidgetPostAPIMediator @Inject constructor(private val moshi: Moshi, private val widgetPostMessageAPIProvider: WidgetPostMessageAPIProvider) : - WidgetPostAPIMediator { + WidgetPostAPIMediator { private val jsonAdapter = moshi.adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetService.kt index 89e827aea00bae3068a2e6c569a3db01d90f4310..53a435d2172c127b22120322974c4b55d66f0fce 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetService.kt @@ -29,7 +29,7 @@ import javax.inject.Provider internal class DefaultWidgetService @Inject constructor(private val widgetManager: WidgetManager, private val widgetURLFormatter: WidgetURLFormatter, private val widgetPostAPIMediator: Provider<WidgetPostAPIMediator>) : - WidgetService { + WidgetService { override fun getWidgetURLFormatter(): WidgetURLFormatter { return widgetURLFormatter @@ -52,7 +52,7 @@ internal class DefaultWidgetService @Inject constructor(private val widgetManage return widgetManager.getWidgetComputedUrl(widget, isLightTheme) } -override fun getRoomWidgetsLive( + override fun getRoomWidgetsLive( roomId: String, widgetId: QueryStringValue, widgetTypes: Set<String>?, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt index e18117d2d7bded184ae2822cb54d24f8e81447ad..07ed91c1790ff82ac64864a968794ff3981f498f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt @@ -52,7 +52,7 @@ internal class WidgetManager @Inject constructor(private val integrationManager: private val widgetFactory: WidgetFactory, @UserId private val userId: String) : - IntegrationManagerService.Listener, SessionLifecycleObserver { + IntegrationManagerService.Listener, SessionLifecycleObserver { private val lifecycleOwner: LifecycleOwner = LifecycleOwner { lifecycleRegistry } private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(lifecycleOwner) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LogUtil.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LogUtil.kt index 6fd907d397235cb45fe8981c64eb9659480b9108..ffad0b856c368d750256bfb254ae2643fa977e9f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LogUtil.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LogUtil.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.util import org.matrix.android.sdk.BuildConfig import org.matrix.android.sdk.api.logger.LoggerTag +import org.matrix.android.sdk.internal.util.time.Clock import timber.log.Timber internal fun <T> Collection<T>.logLimit(maxQuantity: Int = 5): String { @@ -34,13 +35,14 @@ internal fun <T> Collection<T>.logLimit(maxQuantity: Int = 5): String { internal suspend fun <T> logDuration(message: String, loggerTag: LoggerTag, + clock: Clock, block: suspend () -> T): T { Timber.tag(loggerTag.value).d("$message -- BEGIN") - val start = System.currentTimeMillis() + val start = clock.epochMillis() val result = logRamUsage(message) { block() } - val duration = System.currentTimeMillis() - start + val duration = clock.epochMillis() - start Timber.tag(loggerTag.value).d("$message -- END duration: $duration ms") return result diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/TemporaryFileCreator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/TemporaryFileCreator.kt index 2790ffba36f0d982ca4183106d010162b6e6de63..dddd7892125dae027322185c292014530b1257fe 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/TemporaryFileCreator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/TemporaryFileCreator.kt @@ -29,6 +29,7 @@ internal class TemporaryFileCreator @Inject constructor( suspend fun create(): File { return withContext(Dispatchers.IO) { File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir) + .apply { mkdirs() } } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/database/RealmMigrator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/database/RealmMigrator.kt index f22f0810a146c31176cb1d034286b9eed623fdb7..8f3c89f2d4282f9c058c9ab7654e5ccd1e8f429a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/database/RealmMigrator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/database/RealmMigrator.kt @@ -21,7 +21,7 @@ import io.realm.RealmObjectSchema import timber.log.Timber internal abstract class RealmMigrator(private val realm: DynamicRealm, - private val targetSchemaVersion: Int) { + private val targetSchemaVersion: Int) { fun perform() { Timber.d("Migrate ${realm.configuration.realmFileName} to $targetSchemaVersion") doMigrate(realm) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/DefaultBuildVersionSdkIntProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/DefaultBuildVersionSdkIntProvider.kt index 2d5e4b944a50f90182b74ad2b5fc4d23e4310440..806c6e97351b4289fdef0a758fc938228eaa2839 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/DefaultBuildVersionSdkIntProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/DefaultBuildVersionSdkIntProvider.kt @@ -20,6 +20,6 @@ import android.os.Build import javax.inject.Inject internal class DefaultBuildVersionSdkIntProvider @Inject constructor() : - BuildVersionSdkIntProvider { + BuildVersionSdkIntProvider { override fun get() = Build.VERSION.SDK_INT } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/SystemModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/SystemModule.kt index 8a7b50175a2978335d76e83f58a32c5877b7865c..396d12f369c8fb611444f1549dfbc2504830339e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/SystemModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/system/SystemModule.kt @@ -18,10 +18,15 @@ package org.matrix.android.sdk.internal.util.system import dagger.Binds import dagger.Module +import org.matrix.android.sdk.internal.util.time.Clock +import org.matrix.android.sdk.internal.util.time.DefaultClock @Module internal abstract class SystemModule { @Binds abstract fun bindBuildVersionSdkIntProvider(provider: DefaultBuildVersionSdkIntProvider): BuildVersionSdkIntProvider + + @Binds + abstract fun bindClock(clock: DefaultClock): Clock } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/time/Clock.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/time/Clock.kt new file mode 100644 index 0000000000000000000000000000000000000000..4fe9069b4941b0febb9b18640603c233a0f26117 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/time/Clock.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 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.internal.util.time + +import javax.inject.Inject + +internal interface Clock { + fun epochMillis(): Long +} + +internal class DefaultClock @Inject constructor() : Clock { + + /** + * Provides a UTC epoch in milliseconds + * + * This value is not guaranteed to be correct with reality + * as a User can override the system time and date to any values. + */ + override fun epochMillis(): Long { + return System.currentTimeMillis() + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/AlwaysSuccessfulWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/AlwaysSuccessfulWorker.kt index 856d3debcf368b80a4620bdf454b100cf14a89f7..c92b51fcb895370f066e5410a9792e62d31d614a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/AlwaysSuccessfulWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/AlwaysSuccessfulWorker.kt @@ -20,7 +20,7 @@ import androidx.work.Worker import androidx.work.WorkerParameters internal class AlwaysSuccessfulWorker(context: Context, params: WorkerParameters) : - Worker(context, params) { + Worker(context, params) { override fun doWork(): Result { return Result.success() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt index 0b451e9c34f7621a0a02da13ad658c81e87d6836..e56b359f7ab08537c58effbf8ce9c1955ed13ed9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/MatrixWorkerFactory.kt @@ -93,7 +93,7 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage class CheckFactoryWorker(context: Context, workerParameters: WorkerParameters, private val isCreatedByMatrixWorkerFactory: Boolean) : - CoroutineWorker(context, workerParameters) { + CoroutineWorker(context, workerParameters) { // Called by WorkManager if there is no MatrixWorkerFactory constructor(context: Context, workerParameters: WorkerParameters) : this(context, diff --git a/matrix-sdk-android/src/release/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt b/matrix-sdk-android/src/release/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt index 47f6869479d041fa27517ad915b9082652abe19b..0b7bac0d6fb7e15b280fd695467ed241d778f861 100644 --- a/matrix-sdk-android/src/release/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt +++ b/matrix-sdk-android/src/release/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt @@ -27,7 +27,7 @@ import javax.inject.Inject */ @MatrixScope internal class CurlLoggingInterceptor @Inject constructor() : - Interceptor { + Interceptor { @Throws(IOException::class) override fun intercept(chain: Interceptor.Chain): Response { diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushRuleActionsTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRuleActionsTest.kt similarity index 95% rename from matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushRuleActionsTest.kt rename to matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRuleActionsTest.kt index 9bfdea54143970d36b450fb0a8c37f1672e6f79b..1879e8195cbacb3c69e00aade92fbbe417b19920 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushRuleActionsTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRuleActionsTest.kt @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Test import org.matrix.android.sdk.MatrixTest -import org.matrix.android.sdk.api.pushrules.rest.PushRule +import org.matrix.android.sdk.api.session.pushrules.rest.PushRule import org.matrix.android.sdk.internal.di.MoshiProvider class PushRuleActionsTest : MatrixTest { diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushRulesConditionTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRulesConditionTest.kt similarity index 95% rename from matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushRulesConditionTest.kt rename to matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRulesConditionTest.kt index c0b869a90ea878050b1d128850edfd44bdb43df8..95787173da3af05b95f59f40538e82e940a337d8 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushRulesConditionTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/pushrules/PushRulesConditionTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.pushrules +package org.matrix.android.sdk.api.session.pushrules import io.mockk.every import io.mockk.mockk @@ -26,6 +26,7 @@ import org.matrix.android.sdk.MatrixTest import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.room.Room +import org.matrix.android.sdk.api.session.room.members.MembershipService import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent @@ -148,14 +149,22 @@ class PushRulesConditionTest : MatrixTest { val room2JoinedId = "2joined" val room3JoinedId = "3joined" - val roomStub2Joined = mockk<Room> { + val roomMembershipService2 = mockk<MembershipService> { every { getNumberOfJoinedMembers() } returns 2 } - val roomStub3Joined = mockk<Room> { + val roomMembershipService3 = mockk<MembershipService> { every { getNumberOfJoinedMembers() } returns 3 } + val roomStub2Joined = mockk<Room> { + every { membershipService() } returns roomMembershipService2 + } + + val roomStub3Joined = mockk<Room> { + every { membershipService() } returns roomMembershipService3 + } + val roomGetterStub = mockk<RoomGetter> { every { getRoom(room2JoinedId) } returns roomStub2Joined every { getRoom(room3JoinedId) } returns roomStub3Joined